nvidia-nat 1.2.0rc5__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.
- aiq/agent/__init__.py +0 -0
- aiq/agent/base.py +239 -0
- aiq/agent/dual_node.py +67 -0
- aiq/agent/react_agent/__init__.py +0 -0
- aiq/agent/react_agent/agent.py +355 -0
- aiq/agent/react_agent/output_parser.py +104 -0
- aiq/agent/react_agent/prompt.py +41 -0
- aiq/agent/react_agent/register.py +149 -0
- aiq/agent/reasoning_agent/__init__.py +0 -0
- aiq/agent/reasoning_agent/reasoning_agent.py +225 -0
- aiq/agent/register.py +23 -0
- aiq/agent/rewoo_agent/__init__.py +0 -0
- aiq/agent/rewoo_agent/agent.py +411 -0
- aiq/agent/rewoo_agent/prompt.py +108 -0
- aiq/agent/rewoo_agent/register.py +158 -0
- aiq/agent/tool_calling_agent/__init__.py +0 -0
- aiq/agent/tool_calling_agent/agent.py +119 -0
- aiq/agent/tool_calling_agent/register.py +106 -0
- aiq/authentication/__init__.py +14 -0
- aiq/authentication/api_key/__init__.py +14 -0
- aiq/authentication/api_key/api_key_auth_provider.py +96 -0
- aiq/authentication/api_key/api_key_auth_provider_config.py +124 -0
- aiq/authentication/api_key/register.py +26 -0
- aiq/authentication/exceptions/__init__.py +14 -0
- aiq/authentication/exceptions/api_key_exceptions.py +38 -0
- aiq/authentication/http_basic_auth/__init__.py +0 -0
- aiq/authentication/http_basic_auth/http_basic_auth_provider.py +81 -0
- aiq/authentication/http_basic_auth/register.py +30 -0
- aiq/authentication/interfaces.py +93 -0
- aiq/authentication/oauth2/__init__.py +14 -0
- aiq/authentication/oauth2/oauth2_auth_code_flow_provider.py +107 -0
- aiq/authentication/oauth2/oauth2_auth_code_flow_provider_config.py +39 -0
- aiq/authentication/oauth2/register.py +25 -0
- aiq/authentication/register.py +21 -0
- aiq/builder/__init__.py +0 -0
- aiq/builder/builder.py +285 -0
- aiq/builder/component_utils.py +316 -0
- aiq/builder/context.py +264 -0
- aiq/builder/embedder.py +24 -0
- aiq/builder/eval_builder.py +161 -0
- aiq/builder/evaluator.py +29 -0
- aiq/builder/framework_enum.py +24 -0
- aiq/builder/front_end.py +73 -0
- aiq/builder/function.py +344 -0
- aiq/builder/function_base.py +380 -0
- aiq/builder/function_info.py +627 -0
- aiq/builder/intermediate_step_manager.py +174 -0
- aiq/builder/llm.py +25 -0
- aiq/builder/retriever.py +25 -0
- aiq/builder/user_interaction_manager.py +74 -0
- aiq/builder/workflow.py +148 -0
- aiq/builder/workflow_builder.py +1117 -0
- aiq/cli/__init__.py +14 -0
- aiq/cli/cli_utils/__init__.py +0 -0
- aiq/cli/cli_utils/config_override.py +231 -0
- aiq/cli/cli_utils/validation.py +37 -0
- aiq/cli/commands/__init__.py +0 -0
- aiq/cli/commands/configure/__init__.py +0 -0
- aiq/cli/commands/configure/channel/__init__.py +0 -0
- aiq/cli/commands/configure/channel/add.py +28 -0
- aiq/cli/commands/configure/channel/channel.py +36 -0
- aiq/cli/commands/configure/channel/remove.py +30 -0
- aiq/cli/commands/configure/channel/update.py +30 -0
- aiq/cli/commands/configure/configure.py +33 -0
- aiq/cli/commands/evaluate.py +139 -0
- aiq/cli/commands/info/__init__.py +14 -0
- aiq/cli/commands/info/info.py +39 -0
- aiq/cli/commands/info/list_channels.py +32 -0
- aiq/cli/commands/info/list_components.py +129 -0
- aiq/cli/commands/info/list_mcp.py +213 -0
- aiq/cli/commands/registry/__init__.py +14 -0
- aiq/cli/commands/registry/publish.py +88 -0
- aiq/cli/commands/registry/pull.py +118 -0
- aiq/cli/commands/registry/registry.py +38 -0
- aiq/cli/commands/registry/remove.py +108 -0
- aiq/cli/commands/registry/search.py +155 -0
- aiq/cli/commands/sizing/__init__.py +14 -0
- aiq/cli/commands/sizing/calc.py +297 -0
- aiq/cli/commands/sizing/sizing.py +27 -0
- aiq/cli/commands/start.py +246 -0
- aiq/cli/commands/uninstall.py +81 -0
- aiq/cli/commands/validate.py +47 -0
- aiq/cli/commands/workflow/__init__.py +14 -0
- aiq/cli/commands/workflow/templates/__init__.py.j2 +0 -0
- aiq/cli/commands/workflow/templates/config.yml.j2 +16 -0
- aiq/cli/commands/workflow/templates/pyproject.toml.j2 +22 -0
- aiq/cli/commands/workflow/templates/register.py.j2 +5 -0
- aiq/cli/commands/workflow/templates/workflow.py.j2 +36 -0
- aiq/cli/commands/workflow/workflow.py +37 -0
- aiq/cli/commands/workflow/workflow_commands.py +313 -0
- aiq/cli/entrypoint.py +135 -0
- aiq/cli/main.py +44 -0
- aiq/cli/register_workflow.py +488 -0
- aiq/cli/type_registry.py +1000 -0
- aiq/data_models/__init__.py +14 -0
- aiq/data_models/api_server.py +694 -0
- aiq/data_models/authentication.py +231 -0
- aiq/data_models/common.py +171 -0
- aiq/data_models/component.py +54 -0
- aiq/data_models/component_ref.py +168 -0
- aiq/data_models/config.py +406 -0
- aiq/data_models/dataset_handler.py +123 -0
- aiq/data_models/discovery_metadata.py +335 -0
- aiq/data_models/embedder.py +27 -0
- aiq/data_models/evaluate.py +127 -0
- aiq/data_models/evaluator.py +26 -0
- aiq/data_models/front_end.py +26 -0
- aiq/data_models/function.py +30 -0
- aiq/data_models/function_dependencies.py +72 -0
- aiq/data_models/interactive.py +246 -0
- aiq/data_models/intermediate_step.py +302 -0
- aiq/data_models/invocation_node.py +38 -0
- aiq/data_models/llm.py +27 -0
- aiq/data_models/logging.py +26 -0
- aiq/data_models/memory.py +27 -0
- aiq/data_models/object_store.py +44 -0
- aiq/data_models/profiler.py +54 -0
- aiq/data_models/registry_handler.py +26 -0
- aiq/data_models/retriever.py +30 -0
- aiq/data_models/retry_mixin.py +35 -0
- aiq/data_models/span.py +187 -0
- aiq/data_models/step_adaptor.py +64 -0
- aiq/data_models/streaming.py +33 -0
- aiq/data_models/swe_bench_model.py +54 -0
- aiq/data_models/telemetry_exporter.py +26 -0
- aiq/data_models/ttc_strategy.py +30 -0
- aiq/embedder/__init__.py +0 -0
- aiq/embedder/langchain_client.py +41 -0
- aiq/embedder/nim_embedder.py +59 -0
- aiq/embedder/openai_embedder.py +43 -0
- aiq/embedder/register.py +24 -0
- aiq/eval/__init__.py +14 -0
- aiq/eval/config.py +60 -0
- aiq/eval/dataset_handler/__init__.py +0 -0
- aiq/eval/dataset_handler/dataset_downloader.py +106 -0
- aiq/eval/dataset_handler/dataset_filter.py +52 -0
- aiq/eval/dataset_handler/dataset_handler.py +254 -0
- aiq/eval/evaluate.py +506 -0
- aiq/eval/evaluator/__init__.py +14 -0
- aiq/eval/evaluator/base_evaluator.py +73 -0
- aiq/eval/evaluator/evaluator_model.py +45 -0
- aiq/eval/intermediate_step_adapter.py +99 -0
- aiq/eval/rag_evaluator/__init__.py +0 -0
- aiq/eval/rag_evaluator/evaluate.py +178 -0
- aiq/eval/rag_evaluator/register.py +143 -0
- aiq/eval/register.py +23 -0
- aiq/eval/remote_workflow.py +133 -0
- aiq/eval/runners/__init__.py +14 -0
- aiq/eval/runners/config.py +39 -0
- aiq/eval/runners/multi_eval_runner.py +54 -0
- aiq/eval/runtime_event_subscriber.py +52 -0
- aiq/eval/swe_bench_evaluator/__init__.py +0 -0
- aiq/eval/swe_bench_evaluator/evaluate.py +215 -0
- aiq/eval/swe_bench_evaluator/register.py +36 -0
- aiq/eval/trajectory_evaluator/__init__.py +0 -0
- aiq/eval/trajectory_evaluator/evaluate.py +75 -0
- aiq/eval/trajectory_evaluator/register.py +40 -0
- aiq/eval/tunable_rag_evaluator/__init__.py +0 -0
- aiq/eval/tunable_rag_evaluator/evaluate.py +245 -0
- aiq/eval/tunable_rag_evaluator/register.py +52 -0
- aiq/eval/usage_stats.py +41 -0
- aiq/eval/utils/__init__.py +0 -0
- aiq/eval/utils/output_uploader.py +140 -0
- aiq/eval/utils/tqdm_position_registry.py +40 -0
- aiq/eval/utils/weave_eval.py +184 -0
- aiq/experimental/__init__.py +0 -0
- aiq/experimental/decorators/__init__.py +0 -0
- aiq/experimental/decorators/experimental_warning_decorator.py +130 -0
- aiq/experimental/test_time_compute/__init__.py +0 -0
- aiq/experimental/test_time_compute/editing/__init__.py +0 -0
- aiq/experimental/test_time_compute/editing/iterative_plan_refinement_editor.py +147 -0
- aiq/experimental/test_time_compute/editing/llm_as_a_judge_editor.py +204 -0
- aiq/experimental/test_time_compute/editing/motivation_aware_summarization.py +107 -0
- aiq/experimental/test_time_compute/functions/__init__.py +0 -0
- aiq/experimental/test_time_compute/functions/execute_score_select_function.py +105 -0
- aiq/experimental/test_time_compute/functions/its_tool_orchestration_function.py +205 -0
- aiq/experimental/test_time_compute/functions/its_tool_wrapper_function.py +146 -0
- aiq/experimental/test_time_compute/functions/plan_select_execute_function.py +224 -0
- aiq/experimental/test_time_compute/models/__init__.py +0 -0
- aiq/experimental/test_time_compute/models/editor_config.py +132 -0
- aiq/experimental/test_time_compute/models/scoring_config.py +112 -0
- aiq/experimental/test_time_compute/models/search_config.py +120 -0
- aiq/experimental/test_time_compute/models/selection_config.py +154 -0
- aiq/experimental/test_time_compute/models/stage_enums.py +43 -0
- aiq/experimental/test_time_compute/models/strategy_base.py +66 -0
- aiq/experimental/test_time_compute/models/tool_use_config.py +41 -0
- aiq/experimental/test_time_compute/models/ttc_item.py +48 -0
- aiq/experimental/test_time_compute/register.py +36 -0
- aiq/experimental/test_time_compute/scoring/__init__.py +0 -0
- aiq/experimental/test_time_compute/scoring/llm_based_agent_scorer.py +168 -0
- aiq/experimental/test_time_compute/scoring/llm_based_plan_scorer.py +168 -0
- aiq/experimental/test_time_compute/scoring/motivation_aware_scorer.py +111 -0
- aiq/experimental/test_time_compute/search/__init__.py +0 -0
- aiq/experimental/test_time_compute/search/multi_llm_planner.py +128 -0
- aiq/experimental/test_time_compute/search/multi_query_retrieval_search.py +122 -0
- aiq/experimental/test_time_compute/search/single_shot_multi_plan_planner.py +128 -0
- aiq/experimental/test_time_compute/selection/__init__.py +0 -0
- aiq/experimental/test_time_compute/selection/best_of_n_selector.py +63 -0
- aiq/experimental/test_time_compute/selection/llm_based_agent_output_selector.py +131 -0
- aiq/experimental/test_time_compute/selection/llm_based_output_merging_selector.py +159 -0
- aiq/experimental/test_time_compute/selection/llm_based_plan_selector.py +128 -0
- aiq/experimental/test_time_compute/selection/threshold_selector.py +58 -0
- aiq/front_ends/__init__.py +14 -0
- aiq/front_ends/console/__init__.py +14 -0
- aiq/front_ends/console/authentication_flow_handler.py +233 -0
- aiq/front_ends/console/console_front_end_config.py +32 -0
- aiq/front_ends/console/console_front_end_plugin.py +96 -0
- aiq/front_ends/console/register.py +25 -0
- aiq/front_ends/cron/__init__.py +14 -0
- aiq/front_ends/fastapi/__init__.py +14 -0
- aiq/front_ends/fastapi/auth_flow_handlers/__init__.py +0 -0
- aiq/front_ends/fastapi/auth_flow_handlers/http_flow_handler.py +27 -0
- aiq/front_ends/fastapi/auth_flow_handlers/websocket_flow_handler.py +107 -0
- aiq/front_ends/fastapi/fastapi_front_end_config.py +234 -0
- aiq/front_ends/fastapi/fastapi_front_end_controller.py +68 -0
- aiq/front_ends/fastapi/fastapi_front_end_plugin.py +116 -0
- aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py +1092 -0
- aiq/front_ends/fastapi/html_snippets/__init__.py +14 -0
- aiq/front_ends/fastapi/html_snippets/auth_code_grant_success.py +35 -0
- aiq/front_ends/fastapi/intermediate_steps_subscriber.py +80 -0
- aiq/front_ends/fastapi/job_store.py +183 -0
- aiq/front_ends/fastapi/main.py +72 -0
- aiq/front_ends/fastapi/message_handler.py +298 -0
- aiq/front_ends/fastapi/message_validator.py +345 -0
- aiq/front_ends/fastapi/register.py +25 -0
- aiq/front_ends/fastapi/response_helpers.py +195 -0
- aiq/front_ends/fastapi/step_adaptor.py +321 -0
- aiq/front_ends/mcp/__init__.py +14 -0
- aiq/front_ends/mcp/mcp_front_end_config.py +32 -0
- aiq/front_ends/mcp/mcp_front_end_plugin.py +93 -0
- aiq/front_ends/mcp/register.py +27 -0
- aiq/front_ends/mcp/tool_converter.py +242 -0
- aiq/front_ends/register.py +22 -0
- aiq/front_ends/simple_base/__init__.py +14 -0
- aiq/front_ends/simple_base/simple_front_end_plugin_base.py +54 -0
- aiq/llm/__init__.py +0 -0
- aiq/llm/aws_bedrock_llm.py +57 -0
- aiq/llm/nim_llm.py +46 -0
- aiq/llm/openai_llm.py +46 -0
- aiq/llm/register.py +23 -0
- aiq/llm/utils/__init__.py +14 -0
- aiq/llm/utils/env_config_value.py +94 -0
- aiq/llm/utils/error.py +17 -0
- aiq/memory/__init__.py +20 -0
- aiq/memory/interfaces.py +183 -0
- aiq/memory/models.py +112 -0
- aiq/meta/module_to_distro.json +3 -0
- aiq/meta/pypi.md +58 -0
- aiq/object_store/__init__.py +20 -0
- aiq/object_store/in_memory_object_store.py +76 -0
- aiq/object_store/interfaces.py +84 -0
- aiq/object_store/models.py +36 -0
- aiq/object_store/register.py +20 -0
- aiq/observability/__init__.py +14 -0
- aiq/observability/exporter/__init__.py +14 -0
- aiq/observability/exporter/base_exporter.py +449 -0
- aiq/observability/exporter/exporter.py +78 -0
- aiq/observability/exporter/file_exporter.py +33 -0
- aiq/observability/exporter/processing_exporter.py +322 -0
- aiq/observability/exporter/raw_exporter.py +52 -0
- aiq/observability/exporter/span_exporter.py +265 -0
- aiq/observability/exporter_manager.py +335 -0
- aiq/observability/mixin/__init__.py +14 -0
- aiq/observability/mixin/batch_config_mixin.py +26 -0
- aiq/observability/mixin/collector_config_mixin.py +23 -0
- aiq/observability/mixin/file_mixin.py +288 -0
- aiq/observability/mixin/file_mode.py +23 -0
- aiq/observability/mixin/resource_conflict_mixin.py +134 -0
- aiq/observability/mixin/serialize_mixin.py +61 -0
- aiq/observability/mixin/type_introspection_mixin.py +183 -0
- aiq/observability/processor/__init__.py +14 -0
- aiq/observability/processor/batching_processor.py +310 -0
- aiq/observability/processor/callback_processor.py +42 -0
- aiq/observability/processor/intermediate_step_serializer.py +28 -0
- aiq/observability/processor/processor.py +71 -0
- aiq/observability/register.py +96 -0
- aiq/observability/utils/__init__.py +14 -0
- aiq/observability/utils/dict_utils.py +236 -0
- aiq/observability/utils/time_utils.py +31 -0
- aiq/plugins/.namespace +1 -0
- aiq/profiler/__init__.py +0 -0
- aiq/profiler/calc/__init__.py +14 -0
- aiq/profiler/calc/calc_runner.py +627 -0
- aiq/profiler/calc/calculations.py +288 -0
- aiq/profiler/calc/data_models.py +188 -0
- aiq/profiler/calc/plot.py +345 -0
- aiq/profiler/callbacks/__init__.py +0 -0
- aiq/profiler/callbacks/agno_callback_handler.py +295 -0
- aiq/profiler/callbacks/base_callback_class.py +20 -0
- aiq/profiler/callbacks/langchain_callback_handler.py +290 -0
- aiq/profiler/callbacks/llama_index_callback_handler.py +205 -0
- aiq/profiler/callbacks/semantic_kernel_callback_handler.py +238 -0
- aiq/profiler/callbacks/token_usage_base_model.py +27 -0
- aiq/profiler/data_frame_row.py +51 -0
- aiq/profiler/data_models.py +24 -0
- aiq/profiler/decorators/__init__.py +0 -0
- aiq/profiler/decorators/framework_wrapper.py +131 -0
- aiq/profiler/decorators/function_tracking.py +254 -0
- aiq/profiler/forecasting/__init__.py +0 -0
- aiq/profiler/forecasting/config.py +18 -0
- aiq/profiler/forecasting/model_trainer.py +75 -0
- aiq/profiler/forecasting/models/__init__.py +22 -0
- aiq/profiler/forecasting/models/forecasting_base_model.py +40 -0
- aiq/profiler/forecasting/models/linear_model.py +196 -0
- aiq/profiler/forecasting/models/random_forest_regressor.py +268 -0
- aiq/profiler/inference_metrics_model.py +28 -0
- aiq/profiler/inference_optimization/__init__.py +0 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/__init__.py +0 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/nested_stack_analysis.py +460 -0
- aiq/profiler/inference_optimization/bottleneck_analysis/simple_stack_analysis.py +258 -0
- aiq/profiler/inference_optimization/data_models.py +386 -0
- aiq/profiler/inference_optimization/experimental/__init__.py +0 -0
- aiq/profiler/inference_optimization/experimental/concurrency_spike_analysis.py +468 -0
- aiq/profiler/inference_optimization/experimental/prefix_span_analysis.py +405 -0
- aiq/profiler/inference_optimization/llm_metrics.py +212 -0
- aiq/profiler/inference_optimization/prompt_caching.py +163 -0
- aiq/profiler/inference_optimization/token_uniqueness.py +107 -0
- aiq/profiler/inference_optimization/workflow_runtimes.py +72 -0
- aiq/profiler/intermediate_property_adapter.py +102 -0
- aiq/profiler/profile_runner.py +473 -0
- aiq/profiler/utils.py +184 -0
- aiq/registry_handlers/__init__.py +0 -0
- aiq/registry_handlers/local/__init__.py +0 -0
- aiq/registry_handlers/local/local_handler.py +176 -0
- aiq/registry_handlers/local/register_local.py +37 -0
- aiq/registry_handlers/metadata_factory.py +60 -0
- aiq/registry_handlers/package_utils.py +567 -0
- aiq/registry_handlers/pypi/__init__.py +0 -0
- aiq/registry_handlers/pypi/pypi_handler.py +251 -0
- aiq/registry_handlers/pypi/register_pypi.py +40 -0
- aiq/registry_handlers/register.py +21 -0
- aiq/registry_handlers/registry_handler_base.py +157 -0
- aiq/registry_handlers/rest/__init__.py +0 -0
- aiq/registry_handlers/rest/register_rest.py +56 -0
- aiq/registry_handlers/rest/rest_handler.py +237 -0
- aiq/registry_handlers/schemas/__init__.py +0 -0
- aiq/registry_handlers/schemas/headers.py +42 -0
- aiq/registry_handlers/schemas/package.py +68 -0
- aiq/registry_handlers/schemas/publish.py +63 -0
- aiq/registry_handlers/schemas/pull.py +82 -0
- aiq/registry_handlers/schemas/remove.py +36 -0
- aiq/registry_handlers/schemas/search.py +91 -0
- aiq/registry_handlers/schemas/status.py +47 -0
- aiq/retriever/__init__.py +0 -0
- aiq/retriever/interface.py +37 -0
- aiq/retriever/milvus/__init__.py +14 -0
- aiq/retriever/milvus/register.py +81 -0
- aiq/retriever/milvus/retriever.py +228 -0
- aiq/retriever/models.py +74 -0
- aiq/retriever/nemo_retriever/__init__.py +14 -0
- aiq/retriever/nemo_retriever/register.py +60 -0
- aiq/retriever/nemo_retriever/retriever.py +190 -0
- aiq/retriever/register.py +22 -0
- aiq/runtime/__init__.py +14 -0
- aiq/runtime/loader.py +215 -0
- aiq/runtime/runner.py +190 -0
- aiq/runtime/session.py +158 -0
- aiq/runtime/user_metadata.py +130 -0
- aiq/settings/__init__.py +0 -0
- aiq/settings/global_settings.py +318 -0
- aiq/test/.namespace +1 -0
- aiq/tool/__init__.py +0 -0
- aiq/tool/chat_completion.py +74 -0
- aiq/tool/code_execution/README.md +151 -0
- aiq/tool/code_execution/__init__.py +0 -0
- aiq/tool/code_execution/code_sandbox.py +267 -0
- aiq/tool/code_execution/local_sandbox/.gitignore +1 -0
- aiq/tool/code_execution/local_sandbox/Dockerfile.sandbox +60 -0
- aiq/tool/code_execution/local_sandbox/__init__.py +13 -0
- aiq/tool/code_execution/local_sandbox/local_sandbox_server.py +198 -0
- aiq/tool/code_execution/local_sandbox/sandbox.requirements.txt +6 -0
- aiq/tool/code_execution/local_sandbox/start_local_sandbox.sh +50 -0
- aiq/tool/code_execution/register.py +74 -0
- aiq/tool/code_execution/test_code_execution_sandbox.py +414 -0
- aiq/tool/code_execution/utils.py +100 -0
- aiq/tool/datetime_tools.py +42 -0
- aiq/tool/document_search.py +141 -0
- aiq/tool/github_tools/__init__.py +0 -0
- aiq/tool/github_tools/create_github_commit.py +133 -0
- aiq/tool/github_tools/create_github_issue.py +87 -0
- aiq/tool/github_tools/create_github_pr.py +106 -0
- aiq/tool/github_tools/get_github_file.py +106 -0
- aiq/tool/github_tools/get_github_issue.py +166 -0
- aiq/tool/github_tools/get_github_pr.py +256 -0
- aiq/tool/github_tools/update_github_issue.py +100 -0
- aiq/tool/mcp/__init__.py +14 -0
- aiq/tool/mcp/exceptions.py +142 -0
- aiq/tool/mcp/mcp_client.py +255 -0
- aiq/tool/mcp/mcp_tool.py +96 -0
- aiq/tool/memory_tools/__init__.py +0 -0
- aiq/tool/memory_tools/add_memory_tool.py +79 -0
- aiq/tool/memory_tools/delete_memory_tool.py +67 -0
- aiq/tool/memory_tools/get_memory_tool.py +72 -0
- aiq/tool/nvidia_rag.py +95 -0
- aiq/tool/register.py +38 -0
- aiq/tool/retriever.py +89 -0
- aiq/tool/server_tools.py +66 -0
- aiq/utils/__init__.py +0 -0
- aiq/utils/data_models/__init__.py +0 -0
- aiq/utils/data_models/schema_validator.py +58 -0
- aiq/utils/debugging_utils.py +43 -0
- aiq/utils/dump_distro_mapping.py +32 -0
- aiq/utils/exception_handlers/__init__.py +0 -0
- aiq/utils/exception_handlers/automatic_retries.py +289 -0
- aiq/utils/exception_handlers/mcp.py +211 -0
- aiq/utils/exception_handlers/schemas.py +114 -0
- aiq/utils/io/__init__.py +0 -0
- aiq/utils/io/model_processing.py +28 -0
- aiq/utils/io/yaml_tools.py +119 -0
- aiq/utils/log_utils.py +37 -0
- aiq/utils/metadata_utils.py +74 -0
- aiq/utils/optional_imports.py +142 -0
- aiq/utils/producer_consumer_queue.py +178 -0
- aiq/utils/reactive/__init__.py +0 -0
- aiq/utils/reactive/base/__init__.py +0 -0
- aiq/utils/reactive/base/observable_base.py +65 -0
- aiq/utils/reactive/base/observer_base.py +55 -0
- aiq/utils/reactive/base/subject_base.py +79 -0
- aiq/utils/reactive/observable.py +59 -0
- aiq/utils/reactive/observer.py +76 -0
- aiq/utils/reactive/subject.py +131 -0
- aiq/utils/reactive/subscription.py +49 -0
- aiq/utils/settings/__init__.py +0 -0
- aiq/utils/settings/global_settings.py +197 -0
- aiq/utils/string_utils.py +38 -0
- aiq/utils/type_converter.py +290 -0
- aiq/utils/type_utils.py +484 -0
- aiq/utils/url_utils.py +27 -0
- nvidia_nat-1.2.0rc5.dist-info/METADATA +363 -0
- nvidia_nat-1.2.0rc5.dist-info/RECORD +435 -0
- nvidia_nat-1.2.0rc5.dist-info/WHEEL +5 -0
- nvidia_nat-1.2.0rc5.dist-info/entry_points.txt +20 -0
- nvidia_nat-1.2.0rc5.dist-info/licenses/LICENSE-3rd-party.txt +3686 -0
- nvidia_nat-1.2.0rc5.dist-info/licenses/LICENSE.md +201 -0
- nvidia_nat-1.2.0rc5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from datetime import datetime
|
|
17
|
+
from typing import Literal
|
|
18
|
+
|
|
19
|
+
from pydantic import BaseModel
|
|
20
|
+
from pydantic import Field
|
|
21
|
+
from pydantic import field_validator
|
|
22
|
+
|
|
23
|
+
from aiq.builder.builder import Builder
|
|
24
|
+
from aiq.builder.function_info import FunctionInfo
|
|
25
|
+
from aiq.cli.register_workflow import register_function
|
|
26
|
+
from aiq.data_models.function import FunctionBaseConfig
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class GithubListIssueModel(BaseModel):
|
|
30
|
+
state: Literal["open", "closed", "all"] | None = Field('open', description="Issue state used in issue query filter")
|
|
31
|
+
assignee: str | None = Field("*", description="Assignee name used in issue query filter")
|
|
32
|
+
creator: str | None = Field(None, description="Creator name used in issue query filter")
|
|
33
|
+
mentioned: str | None = Field(None, description="Name of person mentioned in issue")
|
|
34
|
+
labels: list[str] | None = Field(None, description="A list of labels that are assigned to the issue")
|
|
35
|
+
since: str | None = Field(None, description="Only show results that were last updated after the given time.")
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
@field_validator('since', mode='before')
|
|
39
|
+
def validate_since(cls, v):
|
|
40
|
+
if v is None:
|
|
41
|
+
return v
|
|
42
|
+
try:
|
|
43
|
+
# Parse the string to a datetime object
|
|
44
|
+
parsed_date = datetime.strptime(v, "%Y-%m-%dT%H:%M:%SZ")
|
|
45
|
+
# Return the formatted string
|
|
46
|
+
return parsed_date.isoformat() + 'Z'
|
|
47
|
+
except ValueError as e:
|
|
48
|
+
raise ValueError("since must be in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ") from e
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class GithubListIssueModelList(BaseModel):
|
|
52
|
+
filter_params: GithubListIssueModel = Field(description=("A list of query params when fetching issues "
|
|
53
|
+
"each of type GithubListIssueModel"))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class GithubListIssueToolConfig(FunctionBaseConfig, name="github_list_issues_tool"):
|
|
57
|
+
"""
|
|
58
|
+
Configuration for the GitHub List Issues Tool.
|
|
59
|
+
"""
|
|
60
|
+
repo_name: str = Field(description="The repository name in the format 'owner/repo'")
|
|
61
|
+
timeout: int = Field(default=300, description="The timeout configuration to use when sending requests.")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@register_function(config_type=GithubListIssueToolConfig)
|
|
65
|
+
async def list_github_issue_async(config: GithubListIssueToolConfig, builder: Builder):
|
|
66
|
+
"""
|
|
67
|
+
Lists GitHub Issues based on various filter parameters
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
import json
|
|
71
|
+
import os
|
|
72
|
+
|
|
73
|
+
import httpx
|
|
74
|
+
|
|
75
|
+
github_pat = os.getenv("GITHUB_PAT")
|
|
76
|
+
if not github_pat:
|
|
77
|
+
raise ValueError("GITHUB_PAT environment variable must be set")
|
|
78
|
+
|
|
79
|
+
url = f"https://api.github.com/repos/{config.repo_name}/issues"
|
|
80
|
+
|
|
81
|
+
# define the headers for the payload request
|
|
82
|
+
headers = {"Authorization": f"Bearer {github_pat}", "Accept": "application/vnd.github+json"}
|
|
83
|
+
|
|
84
|
+
async def _github_list_issues(filter_params) -> dict:
|
|
85
|
+
async with httpx.AsyncClient(timeout=config.timeout) as client:
|
|
86
|
+
|
|
87
|
+
filter_params = filter_params.dict(exclude_unset=True)
|
|
88
|
+
|
|
89
|
+
# filter out None values that are explictly set in the request body.
|
|
90
|
+
filter_params = {k: v for k, v in filter_params.items() if v is not None}
|
|
91
|
+
|
|
92
|
+
response = await client.request("GET", url, params=filter_params, headers=headers)
|
|
93
|
+
|
|
94
|
+
# Raise an exception for HTTP errors
|
|
95
|
+
response.raise_for_status()
|
|
96
|
+
|
|
97
|
+
# Parse and return the response JSON
|
|
98
|
+
try:
|
|
99
|
+
result = response.json()
|
|
100
|
+
|
|
101
|
+
except ValueError as e:
|
|
102
|
+
raise ValueError("The API response is not valid JSON.") from e
|
|
103
|
+
|
|
104
|
+
return json.dumps(result)
|
|
105
|
+
|
|
106
|
+
yield FunctionInfo.from_fn(_github_list_issues,
|
|
107
|
+
description=(f"Lists GitHub issues based on filter "
|
|
108
|
+
f"params in the repo named {config.repo_name}"),
|
|
109
|
+
input_schema=GithubListIssueModelList)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class GithubGetIssueModel(BaseModel):
|
|
113
|
+
issue_number: str = Field(description="The issue number that needs to be fetched")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class GithubGetIssueToolConfig(FunctionBaseConfig, name="github_get_issue_tool"):
|
|
117
|
+
"""
|
|
118
|
+
Tool that fetches a particular issue in a GitHub repository asynchronously.
|
|
119
|
+
"""
|
|
120
|
+
repo_name: str = "The repository name in the format 'owner/repo'"
|
|
121
|
+
timeout: int = 300
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@register_function(config_type=GithubGetIssueToolConfig)
|
|
125
|
+
async def get_github_issue_async(config: GithubGetIssueToolConfig, builder: Builder):
|
|
126
|
+
"""
|
|
127
|
+
Fetches a particular issue in a GitHub repository asynchronously.
|
|
128
|
+
|
|
129
|
+
"""
|
|
130
|
+
import json
|
|
131
|
+
import os
|
|
132
|
+
|
|
133
|
+
import httpx
|
|
134
|
+
|
|
135
|
+
github_pat = os.getenv("GITHUB_PAT")
|
|
136
|
+
if not github_pat:
|
|
137
|
+
raise ValueError("GITHUB_PAT environment variable must be set")
|
|
138
|
+
|
|
139
|
+
url = f"https://api.github.com/repos/{config.repo_name}/issues"
|
|
140
|
+
|
|
141
|
+
# define the headers for the payload request
|
|
142
|
+
headers = {"Authorization": f"Bearer {github_pat}", "Accept": "application/vnd.github+json"}
|
|
143
|
+
|
|
144
|
+
async def _github_get_issue(issue_number) -> list:
|
|
145
|
+
async with httpx.AsyncClient(timeout=config.timeout) as client:
|
|
146
|
+
# update the url with the issue number that needs to be updated
|
|
147
|
+
issue_url = os.path.join(url, issue_number)
|
|
148
|
+
|
|
149
|
+
response = await client.request("GET", issue_url, headers=headers)
|
|
150
|
+
|
|
151
|
+
# Raise an exception for HTTP errors
|
|
152
|
+
response.raise_for_status()
|
|
153
|
+
|
|
154
|
+
# Parse and return the response JSON
|
|
155
|
+
try:
|
|
156
|
+
result = response.json()
|
|
157
|
+
|
|
158
|
+
except ValueError as e:
|
|
159
|
+
raise ValueError("The API response is not valid JSON.") from e
|
|
160
|
+
|
|
161
|
+
return json.dumps(result)
|
|
162
|
+
|
|
163
|
+
yield FunctionInfo.from_fn(_github_get_issue,
|
|
164
|
+
description=(f"Fetches a particular GitHub issue "
|
|
165
|
+
f"in the repo named {config.repo_name}"),
|
|
166
|
+
input_schema=GithubGetIssueModel)
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from typing import Literal
|
|
17
|
+
|
|
18
|
+
from pydantic import BaseModel
|
|
19
|
+
from pydantic import Field
|
|
20
|
+
|
|
21
|
+
from aiq.builder.builder import Builder
|
|
22
|
+
from aiq.builder.function_info import FunctionInfo
|
|
23
|
+
from aiq.cli.register_workflow import register_function
|
|
24
|
+
from aiq.data_models.function import FunctionBaseConfig
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class GithubListPullsModel(BaseModel):
|
|
28
|
+
state: Literal["open", "closed", "all"] | None = Field('open', description="Issue state used in issue query filter")
|
|
29
|
+
head: str | None = Field(None, description="Filters pulls by head user or head organization and branch name")
|
|
30
|
+
base: str | None = Field(None, description="Filters pull by branch name")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class GithubListPullsModelList(BaseModel):
|
|
34
|
+
filter_params: GithubListPullsModel = Field(description=("A list of query params when fetching pull requests "
|
|
35
|
+
"each of type GithubListPRModel"))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class GithubListPullsToolConfig(FunctionBaseConfig, name="github_list_pulls_tool"):
|
|
39
|
+
"""
|
|
40
|
+
Tool that lists GitHub Pull Requests based on various filter parameters
|
|
41
|
+
"""
|
|
42
|
+
repo_name: str = Field(description="The repository name in the format 'owner/repo'")
|
|
43
|
+
timeout: int = Field(default=300, description="The timeout configuration to use when sending requests.")
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@register_function(config_type=GithubListPullsToolConfig)
|
|
47
|
+
async def list_github_pulls_async(config: GithubListPullsToolConfig, builder: Builder):
|
|
48
|
+
"""
|
|
49
|
+
Lists GitHub Pull Requests based on various filter parameters
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
import json
|
|
53
|
+
import os
|
|
54
|
+
|
|
55
|
+
import httpx
|
|
56
|
+
|
|
57
|
+
github_pat = os.getenv("GITHUB_PAT")
|
|
58
|
+
if not github_pat:
|
|
59
|
+
raise ValueError("GITHUB_PAT environment variable must be set")
|
|
60
|
+
|
|
61
|
+
url = f"https://api.github.com/repos/{config.repo_name}/pulls"
|
|
62
|
+
|
|
63
|
+
# define the headers for the payload request
|
|
64
|
+
headers = {"Authorization": f"Bearer {github_pat}", "Accept": "application/vnd.github+json"}
|
|
65
|
+
|
|
66
|
+
async def _github_list_pulls(filter_params) -> dict:
|
|
67
|
+
async with httpx.AsyncClient(timeout=config.timeout) as client:
|
|
68
|
+
|
|
69
|
+
filter_params = filter_params.dict(exclude_unset=True)
|
|
70
|
+
|
|
71
|
+
# filter out None values that are explictly set in the request body.
|
|
72
|
+
filter_params = {k: v for k, v in filter_params.items() if v is not None}
|
|
73
|
+
|
|
74
|
+
response = await client.request("GET", url, params=filter_params, headers=headers)
|
|
75
|
+
|
|
76
|
+
# Raise an exception for HTTP errors
|
|
77
|
+
response.raise_for_status()
|
|
78
|
+
|
|
79
|
+
# Parse and return the response JSON
|
|
80
|
+
try:
|
|
81
|
+
result = response.json()
|
|
82
|
+
|
|
83
|
+
except ValueError as e:
|
|
84
|
+
raise ValueError("The API response is not valid JSON.") from e
|
|
85
|
+
|
|
86
|
+
return json.dumps(result)
|
|
87
|
+
|
|
88
|
+
yield FunctionInfo.from_fn(_github_list_pulls,
|
|
89
|
+
description=(f"Lists GitHub PRs based on filter params "
|
|
90
|
+
f"in the repo named {config.repo_name}"),
|
|
91
|
+
input_schema=GithubListPullsModelList)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class GithubGetPullModel(BaseModel):
|
|
95
|
+
pull_number: str = Field(description="The number of the pull request that needs to be fetched")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class GithubGetPullToolConfig(FunctionBaseConfig, name="github_get_pull_tool"):
|
|
99
|
+
"""
|
|
100
|
+
Tool that fetches a particular pull request in a GitHub repository asynchronously.
|
|
101
|
+
"""
|
|
102
|
+
repo_name: str = "The repository name in the format 'owner/repo'"
|
|
103
|
+
timeout: int = 300
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@register_function(config_type=GithubGetPullToolConfig)
|
|
107
|
+
async def get_github_pull_async(config: GithubGetPullToolConfig, builder: Builder):
|
|
108
|
+
"""
|
|
109
|
+
Fetches a particular pull request in a GitHub repository asynchronously.
|
|
110
|
+
|
|
111
|
+
"""
|
|
112
|
+
import json
|
|
113
|
+
import os
|
|
114
|
+
|
|
115
|
+
import httpx
|
|
116
|
+
|
|
117
|
+
github_pat = os.getenv("GITHUB_PAT")
|
|
118
|
+
if not github_pat:
|
|
119
|
+
raise ValueError("GITHUB_PAT environment variable must be set")
|
|
120
|
+
|
|
121
|
+
url = f"https://api.github.com/repos/{config.repo_name}/pulls"
|
|
122
|
+
|
|
123
|
+
# define the headers for the payload request
|
|
124
|
+
headers = {"Authorization": f"Bearer {github_pat}", "Accept": "application/vnd.github+json"}
|
|
125
|
+
|
|
126
|
+
async def _github_get_pull(pull_number) -> list:
|
|
127
|
+
async with httpx.AsyncClient(timeout=config.timeout) as client:
|
|
128
|
+
# update the url with the pull number that needs to be updated
|
|
129
|
+
pull_url = os.path.join(url, pull_number)
|
|
130
|
+
|
|
131
|
+
response = await client.request("GET", pull_url, headers=headers)
|
|
132
|
+
|
|
133
|
+
# Raise an exception for HTTP errors
|
|
134
|
+
response.raise_for_status()
|
|
135
|
+
|
|
136
|
+
# Parse and return the response JSON
|
|
137
|
+
try:
|
|
138
|
+
result = response.json()
|
|
139
|
+
|
|
140
|
+
except ValueError as e:
|
|
141
|
+
raise ValueError("The API response is not valid JSON.") from e
|
|
142
|
+
|
|
143
|
+
return json.dumps(result)
|
|
144
|
+
|
|
145
|
+
yield FunctionInfo.from_fn(_github_get_pull,
|
|
146
|
+
description=(f"Fetches a particular GitHub pull request "
|
|
147
|
+
f"in the repo named {config.repo_name}"),
|
|
148
|
+
input_schema=GithubGetPullModel)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class GithubGetPullCommitsToolConfig(FunctionBaseConfig, name="github_get_pull_commits_tool"):
|
|
152
|
+
"""
|
|
153
|
+
Configuration for the GitHub Get Pull Commits Tool.
|
|
154
|
+
"""
|
|
155
|
+
repo_name: str = "The repository name in the format 'owner/repo'"
|
|
156
|
+
timeout: int = 300
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@register_function(config_type=GithubGetPullCommitsToolConfig)
|
|
160
|
+
async def get_github_pull_commits_async(config: GithubGetPullCommitsToolConfig, builder: Builder):
|
|
161
|
+
"""
|
|
162
|
+
Fetches the commits associated with a particular pull request in a GitHub repository asynchronously.
|
|
163
|
+
|
|
164
|
+
"""
|
|
165
|
+
import json
|
|
166
|
+
import os
|
|
167
|
+
|
|
168
|
+
import httpx
|
|
169
|
+
|
|
170
|
+
github_pat = os.getenv("GITHUB_PAT")
|
|
171
|
+
if not github_pat:
|
|
172
|
+
raise ValueError("GITHUB_PAT environment variable must be set")
|
|
173
|
+
|
|
174
|
+
url = f"https://api.github.com/repos/{config.repo_name}/pulls"
|
|
175
|
+
|
|
176
|
+
# define the headers for the payload request
|
|
177
|
+
headers = {"Authorization": f"Bearer {github_pat}", "Accept": "application/vnd.github+json"}
|
|
178
|
+
|
|
179
|
+
async def _github_get_pull(pull_number) -> list:
|
|
180
|
+
async with httpx.AsyncClient(timeout=config.timeout) as client:
|
|
181
|
+
# update the url with the pull number that needs to be updated
|
|
182
|
+
pull_url = os.path.join(url, pull_number)
|
|
183
|
+
pull_commits_url = os.path.join(pull_url, "commits")
|
|
184
|
+
|
|
185
|
+
response = await client.request("GET", pull_commits_url, headers=headers)
|
|
186
|
+
|
|
187
|
+
# Raise an exception for HTTP errors
|
|
188
|
+
response.raise_for_status()
|
|
189
|
+
|
|
190
|
+
# Parse and return the response JSON
|
|
191
|
+
try:
|
|
192
|
+
result = response.json()
|
|
193
|
+
|
|
194
|
+
except ValueError as e:
|
|
195
|
+
raise ValueError("The API response is not valid JSON.") from e
|
|
196
|
+
|
|
197
|
+
return json.dumps(result)
|
|
198
|
+
|
|
199
|
+
yield FunctionInfo.from_fn(_github_get_pull,
|
|
200
|
+
description=("Fetches the commits for a particular GitHub pull request "
|
|
201
|
+
f" in the repo named {config.repo_name}"),
|
|
202
|
+
input_schema=GithubGetPullModel)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class GithubGetPullFilesToolConfig(FunctionBaseConfig, name="github_get_pull_files_tool"):
|
|
206
|
+
"""
|
|
207
|
+
Configuration for the GitHub Get Pull Files Tool.
|
|
208
|
+
"""
|
|
209
|
+
repo_name: str = "The repository name in the format 'owner/repo'"
|
|
210
|
+
timeout: int = 300
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@register_function(config_type=GithubGetPullFilesToolConfig)
|
|
214
|
+
async def get_github_pull_files_async(config: GithubGetPullFilesToolConfig, builder: Builder):
|
|
215
|
+
"""
|
|
216
|
+
Fetches the files associated with a particular pull request in a GitHub repository asynchronously.
|
|
217
|
+
|
|
218
|
+
"""
|
|
219
|
+
import json
|
|
220
|
+
import os
|
|
221
|
+
|
|
222
|
+
import httpx
|
|
223
|
+
|
|
224
|
+
github_pat = os.getenv("GITHUB_PAT")
|
|
225
|
+
if not github_pat:
|
|
226
|
+
raise ValueError("GITHUB_PAT environment variable must be set")
|
|
227
|
+
|
|
228
|
+
url = f"https://api.github.com/repos/{config.repo_name}/pulls"
|
|
229
|
+
|
|
230
|
+
# define the headers for the payload request
|
|
231
|
+
headers = {"Authorization": f"Bearer {github_pat}", "Accept": "application/vnd.github+json"}
|
|
232
|
+
|
|
233
|
+
async def _github_get_pull(pull_number) -> list:
|
|
234
|
+
async with httpx.AsyncClient(timeout=config.timeout) as client:
|
|
235
|
+
# update the url with the pull number that needs to be updated
|
|
236
|
+
pull_url = os.path.join(url, pull_number)
|
|
237
|
+
pull_files_url = os.path.join(pull_url, "files")
|
|
238
|
+
|
|
239
|
+
response = await client.request("GET", pull_files_url, headers=headers)
|
|
240
|
+
|
|
241
|
+
# Raise an exception for HTTP errors
|
|
242
|
+
response.raise_for_status()
|
|
243
|
+
|
|
244
|
+
# Parse and return the response JSON
|
|
245
|
+
try:
|
|
246
|
+
result = response.json()
|
|
247
|
+
|
|
248
|
+
except ValueError as e:
|
|
249
|
+
raise ValueError("The API response is not valid JSON.") from e
|
|
250
|
+
|
|
251
|
+
return json.dumps(result)
|
|
252
|
+
|
|
253
|
+
yield FunctionInfo.from_fn(_github_get_pull,
|
|
254
|
+
description=("Fetches the files for a particular GitHub pull request "
|
|
255
|
+
f" in the repo named {config.repo_name}"),
|
|
256
|
+
input_schema=GithubGetPullModel)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from typing import Literal
|
|
17
|
+
|
|
18
|
+
from pydantic import BaseModel
|
|
19
|
+
from pydantic import Field
|
|
20
|
+
|
|
21
|
+
from aiq.builder.builder import Builder
|
|
22
|
+
from aiq.builder.function_info import FunctionInfo
|
|
23
|
+
from aiq.cli.register_workflow import register_function
|
|
24
|
+
from aiq.data_models.function import FunctionBaseConfig
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class GithubUpdateIssueModel(BaseModel):
|
|
28
|
+
issue_number: str = Field(description="The issue number that will be updated")
|
|
29
|
+
title: str | None = Field(None, description="The title of the GitHub Issue")
|
|
30
|
+
body: str | None = Field(None, description="The body of the GitHub Issue")
|
|
31
|
+
state: Literal["open", "closed"] | None = Field(None, description="The new state of the issue")
|
|
32
|
+
|
|
33
|
+
state_reason: Literal["completed", "not_planned", "reopened", None] | None = Field(
|
|
34
|
+
None, description="The reason for changing the state of the issue")
|
|
35
|
+
|
|
36
|
+
labels: list[str] | None = Field(None, description="A list of labels to assign to the issue")
|
|
37
|
+
assignees: list[str] | None = Field(None, description="A list of assignees to assign to the issue")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GithubUpdateIssueModelList(BaseModel):
|
|
41
|
+
issues: list[GithubUpdateIssueModel] = Field(description=("A list of GitHub issues each "
|
|
42
|
+
"of type GithubUpdateIssueModel"))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class GithubUpdateIssueToolConfig(FunctionBaseConfig, name="github_update_issue_tool"):
|
|
46
|
+
"""
|
|
47
|
+
Tool that updates an issue in a GitHub repository asynchronously.
|
|
48
|
+
"""
|
|
49
|
+
repo_name: str = "The repository name in the format 'owner/repo'"
|
|
50
|
+
timeout: int = 300
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@register_function(config_type=GithubUpdateIssueToolConfig)
|
|
54
|
+
async def update_github_issue_async(config: GithubUpdateIssueToolConfig, builder: Builder):
|
|
55
|
+
"""
|
|
56
|
+
Updates an issue in a GitHub repository asynchronously.
|
|
57
|
+
"""
|
|
58
|
+
import json
|
|
59
|
+
import os
|
|
60
|
+
|
|
61
|
+
import httpx
|
|
62
|
+
|
|
63
|
+
github_pat = os.getenv("GITHUB_PAT")
|
|
64
|
+
if not github_pat:
|
|
65
|
+
raise ValueError("GITHUB_PAT environment variable must be set")
|
|
66
|
+
|
|
67
|
+
url = f"https://api.github.com/repos/{config.repo_name}/issues"
|
|
68
|
+
|
|
69
|
+
# define the headers for the payload request
|
|
70
|
+
headers = {"Authorization": f"Bearer {github_pat}", "Accept": "application/vnd.github+json"}
|
|
71
|
+
|
|
72
|
+
async def _github_update_issue(issues) -> list:
|
|
73
|
+
results = []
|
|
74
|
+
async with httpx.AsyncClient(timeout=config.timeout) as client:
|
|
75
|
+
for issue in issues:
|
|
76
|
+
payload = issue.dict(exclude_unset=True)
|
|
77
|
+
|
|
78
|
+
# update the url with the issue number that needs to be updated
|
|
79
|
+
issue_number = payload.pop("issue_number")
|
|
80
|
+
issue_url = os.path.join(url, issue_number)
|
|
81
|
+
|
|
82
|
+
response = await client.request("PATCH", issue_url, json=payload, headers=headers)
|
|
83
|
+
|
|
84
|
+
# Raise an exception for HTTP errors
|
|
85
|
+
response.raise_for_status()
|
|
86
|
+
|
|
87
|
+
# Parse and return the response JSON
|
|
88
|
+
try:
|
|
89
|
+
result = response.json()
|
|
90
|
+
results.append(result)
|
|
91
|
+
|
|
92
|
+
except ValueError as e:
|
|
93
|
+
raise ValueError("The API response is not valid JSON.") from e
|
|
94
|
+
|
|
95
|
+
return json.dumps(results)
|
|
96
|
+
|
|
97
|
+
yield FunctionInfo.from_fn(_github_update_issue,
|
|
98
|
+
description=(f"Updates a GitHub issue in the "
|
|
99
|
+
f"repo named {config.repo_name}"),
|
|
100
|
+
input_schema=GithubUpdateIssueModelList)
|
aiq/tool/mcp/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
from enum import Enum
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MCPErrorCategory(str, Enum):
|
|
20
|
+
"""Categories of MCP errors for structured handling."""
|
|
21
|
+
CONNECTION = "connection"
|
|
22
|
+
TIMEOUT = "timeout"
|
|
23
|
+
SSL = "ssl"
|
|
24
|
+
AUTHENTICATION = "authentication"
|
|
25
|
+
TOOL_NOT_FOUND = "tool_not_found"
|
|
26
|
+
PROTOCOL = "protocol"
|
|
27
|
+
UNKNOWN = "unknown"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class MCPError(Exception):
|
|
31
|
+
"""Base exception for MCP-related errors."""
|
|
32
|
+
|
|
33
|
+
def __init__(self,
|
|
34
|
+
message: str,
|
|
35
|
+
url: str,
|
|
36
|
+
category: MCPErrorCategory = MCPErrorCategory.UNKNOWN,
|
|
37
|
+
suggestions: list[str] | None = None,
|
|
38
|
+
original_exception: Exception | None = None):
|
|
39
|
+
super().__init__(message)
|
|
40
|
+
self.url = url
|
|
41
|
+
self.category = category
|
|
42
|
+
self.suggestions = suggestions or []
|
|
43
|
+
self.original_exception = original_exception
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class MCPConnectionError(MCPError):
|
|
47
|
+
"""Exception for MCP connection failures."""
|
|
48
|
+
|
|
49
|
+
def __init__(self, url: str, original_exception: Exception | None = None):
|
|
50
|
+
super().__init__(f"Unable to connect to MCP server at {url}",
|
|
51
|
+
url=url,
|
|
52
|
+
category=MCPErrorCategory.CONNECTION,
|
|
53
|
+
suggestions=[
|
|
54
|
+
"Please ensure the MCP server is running and accessible",
|
|
55
|
+
"Check if the URL and port are correct"
|
|
56
|
+
],
|
|
57
|
+
original_exception=original_exception)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MCPTimeoutError(MCPError):
|
|
61
|
+
"""Exception for MCP timeout errors."""
|
|
62
|
+
|
|
63
|
+
def __init__(self, url: str, original_exception: Exception | None = None):
|
|
64
|
+
super().__init__(f"Connection timed out to MCP server at {url}",
|
|
65
|
+
url=url,
|
|
66
|
+
category=MCPErrorCategory.TIMEOUT,
|
|
67
|
+
suggestions=[
|
|
68
|
+
"The server may be overloaded or network is slow",
|
|
69
|
+
"Try again in a moment or check network connectivity"
|
|
70
|
+
],
|
|
71
|
+
original_exception=original_exception)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class MCPSSLError(MCPError):
|
|
75
|
+
"""Exception for MCP SSL/TLS errors."""
|
|
76
|
+
|
|
77
|
+
def __init__(self, url: str, original_exception: Exception | None = None):
|
|
78
|
+
super().__init__(f"SSL/TLS error connecting to {url}",
|
|
79
|
+
url=url,
|
|
80
|
+
category=MCPErrorCategory.SSL,
|
|
81
|
+
suggestions=[
|
|
82
|
+
"Check if the server requires HTTPS or has valid certificates",
|
|
83
|
+
"Try using HTTP instead of HTTPS if appropriate"
|
|
84
|
+
],
|
|
85
|
+
original_exception=original_exception)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class MCPRequestError(MCPError):
|
|
89
|
+
"""Exception for MCP request errors."""
|
|
90
|
+
|
|
91
|
+
def __init__(self, url: str, original_exception: Exception | None = None):
|
|
92
|
+
message = f"Request failed to MCP server at {url}"
|
|
93
|
+
if original_exception:
|
|
94
|
+
message += f": {original_exception}"
|
|
95
|
+
|
|
96
|
+
super().__init__(message,
|
|
97
|
+
url=url,
|
|
98
|
+
category=MCPErrorCategory.PROTOCOL,
|
|
99
|
+
suggestions=["Check the server URL format and network settings"],
|
|
100
|
+
original_exception=original_exception)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class MCPToolNotFoundError(MCPError):
|
|
104
|
+
"""Exception for when a specific MCP tool is not found."""
|
|
105
|
+
|
|
106
|
+
def __init__(self, tool_name: str, url: str, original_exception: Exception | None = None):
|
|
107
|
+
super().__init__(f"Tool '{tool_name}' not available at {url}",
|
|
108
|
+
url=url,
|
|
109
|
+
category=MCPErrorCategory.TOOL_NOT_FOUND,
|
|
110
|
+
suggestions=[
|
|
111
|
+
"Use 'aiq info mcp --detail' to see available tools",
|
|
112
|
+
"Check that the tool name is spelled correctly"
|
|
113
|
+
],
|
|
114
|
+
original_exception=original_exception)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class MCPAuthenticationError(MCPError):
|
|
118
|
+
"""Exception for MCP authentication failures."""
|
|
119
|
+
|
|
120
|
+
def __init__(self, url: str, original_exception: Exception | None = None):
|
|
121
|
+
super().__init__(f"Authentication failed when connecting to MCP server at {url}",
|
|
122
|
+
url=url,
|
|
123
|
+
category=MCPErrorCategory.AUTHENTICATION,
|
|
124
|
+
suggestions=[
|
|
125
|
+
"Check if the server requires authentication credentials",
|
|
126
|
+
"Verify that your credentials are correct and not expired"
|
|
127
|
+
],
|
|
128
|
+
original_exception=original_exception)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class MCPProtocolError(MCPError):
|
|
132
|
+
"""Exception for MCP protocol-related errors."""
|
|
133
|
+
|
|
134
|
+
def __init__(self, url: str, message: str = "Protocol error", original_exception: Exception | None = None):
|
|
135
|
+
super().__init__(f"{message} (MCP server at {url})",
|
|
136
|
+
url=url,
|
|
137
|
+
category=MCPErrorCategory.PROTOCOL,
|
|
138
|
+
suggestions=[
|
|
139
|
+
"Check that the MCP server is running and accessible at this URL",
|
|
140
|
+
"Verify the server supports the expected MCP protocol version"
|
|
141
|
+
],
|
|
142
|
+
original_exception=original_exception)
|