agentcore-cli 0.31.1__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.
- agentcore/__init__.py +1 -0
- agentcore/agent_inspector/NOTICE +9 -0
- agentcore/agent_inspector/favicon.svg +60 -0
- agentcore/agent_inspector/index.css +1 -0
- agentcore/agent_inspector/index.html +14 -0
- agentcore/agent_inspector/index.js +289 -0
- agentcore/assets/AGENTS.md +60 -0
- agentcore/assets/README.md +108 -0
- agentcore/assets/agents/AGENTS.md +218 -0
- agentcore/assets/cdk/.prettierrc +8 -0
- agentcore/assets/cdk/README.md +26 -0
- agentcore/assets/cdk/bin/cdk.ts +216 -0
- agentcore/assets/cdk/cdk.json +88 -0
- agentcore/assets/cdk/gitignore.template +9 -0
- agentcore/assets/cdk/jest.config.js +9 -0
- agentcore/assets/cdk/lib/cdk-stack.ts +291 -0
- agentcore/assets/cdk/npmignore.template +6 -0
- agentcore/assets/cdk/package.json +30 -0
- agentcore/assets/cdk/test/cdk.test.ts +31 -0
- agentcore/assets/cdk/tsconfig.json +28 -0
- agentcore/assets/container/python/Dockerfile +47 -0
- agentcore/assets/container/python/dockerignore.template +27 -0
- agentcore/assets/container/typescript/Dockerfile +25 -0
- agentcore/assets/container/typescript/dockerignore.template +24 -0
- agentcore/assets/datasets/predefined-v1.jsonl +3 -0
- agentcore/assets/datasets/simulated-v1.jsonl +3 -0
- agentcore/assets/evaluators/autoevals-lambda/execution-role-policy.json +15 -0
- agentcore/assets/evaluators/autoevals-lambda/lambda_function.py +37 -0
- agentcore/assets/evaluators/autoevals-lambda/pyproject.toml +22 -0
- agentcore/assets/evaluators/deepeval-lambda/execution-role-policy.json +15 -0
- agentcore/assets/evaluators/deepeval-lambda/lambda_function.py +29 -0
- agentcore/assets/evaluators/deepeval-lambda/pyproject.toml +19 -0
- agentcore/assets/evaluators/python-lambda/execution-role-policy.json +10 -0
- agentcore/assets/evaluators/python-lambda/lambda_function.py +19 -0
- agentcore/assets/evaluators/python-lambda/pyproject.toml +15 -0
- agentcore/assets/harness/invoke.py.template +74 -0
- agentcore/assets/mcp/python/README.md +27 -0
- agentcore/assets/mcp/python/pyproject.toml +22 -0
- agentcore/assets/mcp/python/server.py +117 -0
- agentcore/assets/mcp/python-lambda/README.md +22 -0
- agentcore/assets/mcp/python-lambda/handler.py +144 -0
- agentcore/assets/mcp/python-lambda/pyproject.toml +15 -0
- agentcore/assets/python/a2a/googleadk/base/README.md +22 -0
- agentcore/assets/python/a2a/googleadk/base/gitignore.template +41 -0
- agentcore/assets/python/a2a/googleadk/base/main.py +124 -0
- agentcore/assets/python/a2a/googleadk/base/model/__init__.py +1 -0
- agentcore/assets/python/a2a/googleadk/base/model/load.py +41 -0
- agentcore/assets/python/a2a/googleadk/base/pyproject.toml +22 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/README.md +22 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/gitignore.template +41 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/main.py +144 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/model/__init__.py +1 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/model/load.py +123 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/pyproject.toml +26 -0
- agentcore/assets/python/a2a/strands/base/README.md +22 -0
- agentcore/assets/python/a2a/strands/base/gitignore.template +41 -0
- agentcore/assets/python/a2a/strands/base/main.py +113 -0
- agentcore/assets/python/a2a/strands/base/model/__init__.py +1 -0
- agentcore/assets/python/a2a/strands/base/model/load.py +123 -0
- agentcore/assets/python/a2a/strands/base/pyproject.toml +23 -0
- agentcore/assets/python/a2a/strands/capabilities/memory/__init__.py +1 -0
- agentcore/assets/python/a2a/strands/capabilities/memory/session.py +46 -0
- agentcore/assets/python/agui/googleadk/base/README.md +30 -0
- agentcore/assets/python/agui/googleadk/base/gitignore.template +41 -0
- agentcore/assets/python/agui/googleadk/base/main.py +91 -0
- agentcore/assets/python/agui/googleadk/base/model/__init__.py +1 -0
- agentcore/assets/python/agui/googleadk/base/model/load.py +41 -0
- agentcore/assets/python/agui/googleadk/base/pyproject.toml +25 -0
- agentcore/assets/python/agui/langchain_langgraph/base/README.md +22 -0
- agentcore/assets/python/agui/langchain_langgraph/base/gitignore.template +41 -0
- agentcore/assets/python/agui/langchain_langgraph/base/main.py +130 -0
- agentcore/assets/python/agui/langchain_langgraph/base/model/__init__.py +1 -0
- agentcore/assets/python/agui/langchain_langgraph/base/model/load.py +123 -0
- agentcore/assets/python/agui/langchain_langgraph/base/pyproject.toml +31 -0
- agentcore/assets/python/agui/strands/base/README.md +22 -0
- agentcore/assets/python/agui/strands/base/gitignore.template +41 -0
- agentcore/assets/python/agui/strands/base/main.py +105 -0
- agentcore/assets/python/agui/strands/base/model/__init__.py +1 -0
- agentcore/assets/python/agui/strands/base/model/load.py +123 -0
- agentcore/assets/python/agui/strands/base/pyproject.toml +27 -0
- agentcore/assets/python/agui/strands/capabilities/memory/__init__.py +1 -0
- agentcore/assets/python/agui/strands/capabilities/memory/session.py +46 -0
- agentcore/assets/python/http/autogen/base/README.md +45 -0
- agentcore/assets/python/http/autogen/base/gitignore.template +41 -0
- agentcore/assets/python/http/autogen/base/main.py +145 -0
- agentcore/assets/python/http/autogen/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/autogen/base/mcp_client/client.py +28 -0
- agentcore/assets/python/http/autogen/base/model/__init__.py +1 -0
- agentcore/assets/python/http/autogen/base/model/load.py +136 -0
- agentcore/assets/python/http/autogen/base/pyproject.toml +34 -0
- agentcore/assets/python/http/bma/base/Dockerfile +41 -0
- agentcore/assets/python/http/bma/base/README.md +178 -0
- agentcore/assets/python/http/bma/base/client.py +200 -0
- agentcore/assets/python/http/bma/base/lifecycle/server.py +641 -0
- agentcore/assets/python/http/bma/base/otel/collector.yaml +69 -0
- agentcore/assets/python/http/bma/base/plugins/acr-report/.codex-plugin/plugin.json +6 -0
- agentcore/assets/python/http/bma/base/plugins/acr-report/skills/acr-report/SKILL.md +16 -0
- agentcore/assets/python/http/bma/base/policies/bma-acr-policy.json +11 -0
- agentcore/assets/python/http/bma/base/policies/bma-session-policy.json +35 -0
- agentcore/assets/python/http/bma/base/policies/bma-session-trust.json +20 -0
- agentcore/assets/python/http/bma/base/pyproject.toml +21 -0
- agentcore/assets/python/http/googleadk/base/README.md +45 -0
- agentcore/assets/python/http/googleadk/base/gitignore.template +41 -0
- agentcore/assets/python/http/googleadk/base/main.py +207 -0
- agentcore/assets/python/http/googleadk/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/googleadk/base/mcp_client/client.py +75 -0
- agentcore/assets/python/http/googleadk/base/model/__init__.py +1 -0
- agentcore/assets/python/http/googleadk/base/model/load.py +41 -0
- agentcore/assets/python/http/googleadk/base/pyproject.toml +24 -0
- agentcore/assets/python/http/langchain_langgraph/base/README.md +45 -0
- agentcore/assets/python/http/langchain_langgraph/base/gitignore.template +41 -0
- agentcore/assets/python/http/langchain_langgraph/base/main.py +227 -0
- agentcore/assets/python/http/langchain_langgraph/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/langchain_langgraph/base/mcp_client/client.py +79 -0
- agentcore/assets/python/http/langchain_langgraph/base/model/__init__.py +1 -0
- agentcore/assets/python/http/langchain_langgraph/base/model/load.py +123 -0
- agentcore/assets/python/http/langchain_langgraph/base/pyproject.toml +38 -0
- agentcore/assets/python/http/openaiagents/base/README.md +45 -0
- agentcore/assets/python/http/openaiagents/base/gitignore.template +41 -0
- agentcore/assets/python/http/openaiagents/base/main.py +200 -0
- agentcore/assets/python/http/openaiagents/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/openaiagents/base/mcp_client/client.py +74 -0
- agentcore/assets/python/http/openaiagents/base/model/__init__.py +1 -0
- agentcore/assets/python/http/openaiagents/base/model/load.py +37 -0
- agentcore/assets/python/http/openaiagents/base/pyproject.toml +21 -0
- agentcore/assets/python/http/strands/base/README.md +46 -0
- agentcore/assets/python/http/strands/base/gitignore.template +41 -0
- agentcore/assets/python/http/strands/base/main.py +714 -0
- agentcore/assets/python/http/strands/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/strands/base/mcp_client/client.py +116 -0
- agentcore/assets/python/http/strands/base/model/__init__.py +1 -0
- agentcore/assets/python/http/strands/base/model/load.py +239 -0
- agentcore/assets/python/http/strands/base/model/mantle_compat.py +21 -0
- agentcore/assets/python/http/strands/base/pyproject.toml +31 -0
- agentcore/assets/python/http/strands/base/skills/fetcher.py +279 -0
- agentcore/assets/python/http/strands/capabilities/execution-limits/hooks/execution_limits.py +54 -0
- agentcore/assets/python/http/strands/capabilities/memory/__init__.py +1 -0
- agentcore/assets/python/http/strands/capabilities/memory/session.py +47 -0
- agentcore/assets/python/http/strands/capabilities/payments/__init__.py +4 -0
- agentcore/assets/python/http/strands/capabilities/payments/payments.py +142 -0
- agentcore/assets/python/mcp/standalone/base/README.md +36 -0
- agentcore/assets/python/mcp/standalone/base/gitignore.template +41 -0
- agentcore/assets/python/mcp/standalone/base/main.py +83 -0
- agentcore/assets/python/mcp/standalone/base/pyproject.toml +16 -0
- agentcore/assets/typescript/.gitkeep +0 -0
- agentcore/assets/typescript/http/strands/base/README.md +42 -0
- agentcore/assets/typescript/http/strands/base/gitignore.template +22 -0
- agentcore/assets/typescript/http/strands/base/main.ts +149 -0
- agentcore/assets/typescript/http/strands/base/mcp_client/client.ts +11 -0
- agentcore/assets/typescript/http/strands/base/model/load.ts +102 -0
- agentcore/assets/typescript/http/strands/base/package.json +38 -0
- agentcore/assets/typescript/http/strands/base/tsconfig.json +19 -0
- agentcore/assets/typescript/http/strands/capabilities/memory/memory.ts +52 -0
- agentcore/assets/typescript/http/vercelai/base/README.md +42 -0
- agentcore/assets/typescript/http/vercelai/base/gitignore.template +22 -0
- agentcore/assets/typescript/http/vercelai/base/main.ts +70 -0
- agentcore/assets/typescript/http/vercelai/base/model/load.ts +121 -0
- agentcore/assets/typescript/http/vercelai/base/package.json +35 -0
- agentcore/assets/typescript/http/vercelai/base/tsconfig.json +19 -0
- agentcore/aws/__init__.py +263 -0
- agentcore/aws/_aws_errors.py +72 -0
- agentcore/aws/_http.py +176 -0
- agentcore/aws/_util.py +37 -0
- agentcore/aws/account.py +165 -0
- agentcore/aws/agentcore.py +971 -0
- agentcore/aws/agentcore_ab_tests.py +230 -0
- agentcore/aws/agentcore_batch_evaluation.py +227 -0
- agentcore/aws/agentcore_config_bundles.py +220 -0
- agentcore/aws/agentcore_control.py +994 -0
- agentcore/aws/agentcore_datasets.py +222 -0
- agentcore/aws/agentcore_harness.py +330 -0
- agentcore/aws/agentcore_payments.py +430 -0
- agentcore/aws/agentcore_recommendation.py +140 -0
- agentcore/aws/agui_parser.py +131 -0
- agentcore/aws/agui_types.py +342 -0
- agentcore/aws/api_client.py +87 -0
- agentcore/aws/arn.py +18 -0
- agentcore/aws/aws_context.py +23 -0
- agentcore/aws/bedrock.py +44 -0
- agentcore/aws/bedrock_agent.py +129 -0
- agentcore/aws/bedrock_import.py +252 -0
- agentcore/aws/bedrock_import_types.py +111 -0
- agentcore/aws/cloudwatch.py +136 -0
- agentcore/aws/connect_shell.py +266 -0
- agentcore/aws/iam.py +41 -0
- agentcore/aws/partition.py +58 -0
- agentcore/aws/policy_generation.py +116 -0
- agentcore/aws/region.py +54 -0
- agentcore/aws/retry.py +27 -0
- agentcore/aws/shell_framer.py +136 -0
- agentcore/aws/stage_endpoint.py +39 -0
- agentcore/aws/target_region.py +54 -0
- agentcore/aws/transaction_search.py +97 -0
- agentcore/cdk/__init__.py +10 -0
- agentcore/cdk/constants.py +13 -0
- agentcore/cdk/local_cdk_project.py +48 -0
- agentcore/cdk/toolkit.py +706 -0
- agentcore/cli/__init__.py +0 -0
- agentcore/cli/commands/__init__.py +0 -0
- agentcore/cli/commands/_jobs_common.py +39 -0
- agentcore/cli/commands/_run_wizards.py +639 -0
- agentcore/cli/commands/add/__init__.py +37 -0
- agentcore/cli/commands/add/_commander.py +52 -0
- agentcore/cli/commands/add/_common.py +47 -0
- agentcore/cli/commands/add/agent_wizard.py +528 -0
- agentcore/cli/commands/add/auth_options.py +154 -0
- agentcore/cli/commands/add/skill_action.py +105 -0
- agentcore/cli/commands/add/skill_command.py +87 -0
- agentcore/cli/commands/add/tool_action.py +160 -0
- agentcore/cli/commands/add/tool_command.py +117 -0
- agentcore/cli/commands/add/validate.py +333 -0
- agentcore/cli/commands/capacity_provider/__init__.py +86 -0
- agentcore/cli/commands/capacity_provider/action.py +114 -0
- agentcore/cli/commands/capacity_provider/constants.py +22 -0
- agentcore/cli/commands/config.py +91 -0
- agentcore/cli/commands/config_bundle.py +251 -0
- agentcore/cli/commands/create/__init__.py +643 -0
- agentcore/cli/commands/create/action.py +406 -0
- agentcore/cli/commands/create/dependencies.py +91 -0
- agentcore/cli/commands/create/harness_validate.py +82 -0
- agentcore/cli/commands/create/validate.py +195 -0
- agentcore/cli/commands/create/wizard.py +127 -0
- agentcore/cli/commands/dataset.py +119 -0
- agentcore/cli/commands/deploy/__init__.py +31 -0
- agentcore/cli/commands/deploy/_guards.py +25 -0
- agentcore/cli/commands/deploy/actions.py +840 -0
- agentcore/cli/commands/deploy/command.py +349 -0
- agentcore/cli/commands/deploy/progress.py +115 -0
- agentcore/cli/commands/deploy/types.py +68 -0
- agentcore/cli/commands/deploy/utils.py +43 -0
- agentcore/cli/commands/deploy/validate.py +21 -0
- agentcore/cli/commands/dev/__init__.py +5 -0
- agentcore/cli/commands/dev/_deps.py +50 -0
- agentcore/cli/commands/dev/browser_mode.py +270 -0
- agentcore/cli/commands/dev/command.py +450 -0
- agentcore/cli/commands/dev/terminal_mode.py +379 -0
- agentcore/cli/commands/exec/__init__.py +29 -0
- agentcore/cli/commands/exec/action.py +442 -0
- agentcore/cli/commands/exec/command.py +206 -0
- agentcore/cli/commands/exec/types.py +35 -0
- agentcore/cli/commands/export/__init__.py +114 -0
- agentcore/cli/commands/export/constants.py +21 -0
- agentcore/cli/commands/export/fetch_harness_spec.py +234 -0
- agentcore/cli/commands/export/harness_action.py +385 -0
- agentcore/cli/commands/export/harness_mapper.py +868 -0
- agentcore/cli/commands/export/harness_resolver.py +95 -0
- agentcore/cli/commands/export/types.py +90 -0
- agentcore/cli/commands/export/wizard.py +97 -0
- agentcore/cli/commands/feedback/__init__.py +69 -0
- agentcore/cli/commands/feedback/action.py +30 -0
- agentcore/cli/commands/feedback/consent_prompt.py +35 -0
- agentcore/cli/commands/feedback/wizard.py +49 -0
- agentcore/cli/commands/fetch/__init__.py +69 -0
- agentcore/cli/commands/fetch/action.py +62 -0
- agentcore/cli/commands/help.py +65 -0
- agentcore/cli/commands/import_/__init__.py +167 -0
- agentcore/cli/commands/import_/_js.py +72 -0
- agentcore/cli/commands/import_/actions.py +457 -0
- agentcore/cli/commands/import_/constants.py +45 -0
- agentcore/cli/commands/import_/import_evaluator.py +140 -0
- agentcore/cli/commands/import_/import_gateway.py +520 -0
- agentcore/cli/commands/import_/import_memory.py +128 -0
- agentcore/cli/commands/import_/import_online_eval.py +165 -0
- agentcore/cli/commands/import_/import_pipeline.py +145 -0
- agentcore/cli/commands/import_/import_runtime.py +214 -0
- agentcore/cli/commands/import_/import_utils.py +410 -0
- agentcore/cli/commands/import_/phase1_update.py +110 -0
- agentcore/cli/commands/import_/phase2_import.py +206 -0
- agentcore/cli/commands/import_/resource_import.py +228 -0
- agentcore/cli/commands/import_/template_utils.py +148 -0
- agentcore/cli/commands/import_/types.py +150 -0
- agentcore/cli/commands/import_/yaml_parser.py +265 -0
- agentcore/cli/commands/init.py +196 -0
- agentcore/cli/commands/invoke/__init__.py +32 -0
- agentcore/cli/commands/invoke/_deps.py +73 -0
- agentcore/cli/commands/invoke/action.py +840 -0
- agentcore/cli/commands/invoke/command.py +490 -0
- agentcore/cli/commands/invoke/constants.py +40 -0
- agentcore/cli/commands/invoke/guards.py +23 -0
- agentcore/cli/commands/invoke/interactive.py +604 -0
- agentcore/cli/commands/invoke/resolve.py +149 -0
- agentcore/cli/commands/invoke/resolve_prompt.py +60 -0
- agentcore/cli/commands/invoke/types.py +61 -0
- agentcore/cli/commands/invoke/validate.py +33 -0
- agentcore/cli/commands/job_actions.py +239 -0
- agentcore/cli/commands/job_history.py +380 -0
- agentcore/cli/commands/logs/__init__.py +53 -0
- agentcore/cli/commands/logs/action.py +159 -0
- agentcore/cli/commands/logs/filter_pattern.py +17 -0
- agentcore/cli/commands/logs/guards.py +51 -0
- agentcore/cli/commands/logs_evals.py +42 -0
- agentcore/cli/commands/package.py +118 -0
- agentcore/cli/commands/remove/__init__.py +172 -0
- agentcore/cli/commands/remove/skill_command.py +131 -0
- agentcore/cli/commands/remove/tool_command.py +59 -0
- agentcore/cli/commands/run.py +808 -0
- agentcore/cli/commands/run_ingest.py +97 -0
- agentcore/cli/commands/shared/__init__.py +0 -0
- agentcore/cli/commands/shared/arn_utils.py +9 -0
- agentcore/cli/commands/shared/filesystem_utils.py +421 -0
- agentcore/cli/commands/shared/header_utils.py +87 -0
- agentcore/cli/commands/shared/indexed_key_parser.py +76 -0
- agentcore/cli/commands/shared/lifecycle_utils.py +72 -0
- agentcore/cli/commands/shared/region_utils.py +20 -0
- agentcore/cli/commands/shared/vpc_utils.py +99 -0
- agentcore/cli/commands/status/__init__.py +30 -0
- agentcore/cli/commands/status/_guards.py +25 -0
- agentcore/cli/commands/status/action.py +741 -0
- agentcore/cli/commands/status/command.py +321 -0
- agentcore/cli/commands/status/constants.py +36 -0
- agentcore/cli/commands/status/format_knowledge_base.py +111 -0
- agentcore/cli/commands/telemetry.py +79 -0
- agentcore/cli/commands/traces/__init__.py +155 -0
- agentcore/cli/commands/traces/action.py +123 -0
- agentcore/cli/commands/update/__init__.py +63 -0
- agentcore/cli/commands/update/action.py +164 -0
- agentcore/cli/commands/validate.py +165 -0
- agentcore/cli/constants.py +96 -0
- agentcore/cli/errors.py +118 -0
- agentcore/cli/external_requirements/__init__.py +67 -0
- agentcore/cli/external_requirements/checks.py +280 -0
- agentcore/cli/external_requirements/detect.py +55 -0
- agentcore/cli/external_requirements/versions.py +57 -0
- agentcore/cli/groups.py +23 -0
- agentcore/cli/interactive.py +85 -0
- agentcore/cli/main.py +137 -0
- agentcore/cli/naming.py +11 -0
- agentcore/cli/notices.py +42 -0
- agentcore/cli/project.py +34 -0
- agentcore/cli/run_command.py +27 -0
- agentcore/cli/tree.py +135 -0
- agentcore/cli/update_notifier.py +123 -0
- agentcore/cli/variadic.py +50 -0
- agentcore/cloudformation/__init__.py +84 -0
- agentcore/cloudformation/bootstrap.py +64 -0
- agentcore/cloudformation/logical_ids.py +37 -0
- agentcore/cloudformation/outputs.py +566 -0
- agentcore/cloudformation/stack_discovery.py +75 -0
- agentcore/cloudformation/stack_events.py +107 -0
- agentcore/cloudformation/stack_status.py +98 -0
- agentcore/cloudformation/types.py +44 -0
- agentcore/lib/__init__.py +68 -0
- agentcore/lib/constants.py +77 -0
- agentcore/lib/dependency_management/__init__.py +23 -0
- agentcore/lib/dependency_management/messages.py +92 -0
- agentcore/lib/dependency_management/plan.py +98 -0
- agentcore/lib/dependency_management/semver.py +137 -0
- agentcore/lib/dependency_management/sync.py +139 -0
- agentcore/lib/dependency_management/types.py +56 -0
- agentcore/lib/errors/__init__.py +5 -0
- agentcore/lib/errors/types.py +352 -0
- agentcore/lib/errors/validation.py +121 -0
- agentcore/lib/packaging/__init__.py +81 -0
- agentcore/lib/packaging/build_args.py +23 -0
- agentcore/lib/packaging/build_context.py +26 -0
- agentcore/lib/packaging/build_context_dockerignore.py +45 -0
- agentcore/lib/packaging/container.py +95 -0
- agentcore/lib/packaging/helpers.py +289 -0
- agentcore/lib/packaging/node.py +153 -0
- agentcore/lib/packaging/python.py +135 -0
- agentcore/lib/packaging/types.py +69 -0
- agentcore/lib/packaging/uv.py +45 -0
- agentcore/lib/result.py +104 -0
- agentcore/lib/schemas/__init__.py +1 -0
- agentcore/lib/schemas/io/__init__.py +27 -0
- agentcore/lib/schemas/io/config_io.py +458 -0
- agentcore/lib/schemas/io/global_config.py +239 -0
- agentcore/lib/schemas/io/path_resolver.py +132 -0
- agentcore/lib/secrets/__init__.py +18 -0
- agentcore/lib/secrets/cipher.py +70 -0
- agentcore/lib/secrets/key_provider.py +163 -0
- agentcore/lib/secrets/sensitive_keys.py +55 -0
- agentcore/lib/time_constants.py +4 -0
- agentcore/lib/utils/__init__.py +47 -0
- agentcore/lib/utils/aws_account.py +15 -0
- agentcore/lib/utils/credentials.py +68 -0
- agentcore/lib/utils/dotenv.py +32 -0
- agentcore/lib/utils/env.py +105 -0
- agentcore/lib/utils/json_format.py +29 -0
- agentcore/lib/utils/json_rpc.py +22 -0
- agentcore/lib/utils/platform.py +33 -0
- agentcore/lib/utils/polling.py +86 -0
- agentcore/lib/utils/subprocess.py +135 -0
- agentcore/lib/utils/time_parser.py +48 -0
- agentcore/lib/utils/validation.py +106 -0
- agentcore/logging/__init__.py +10 -0
- agentcore/logging/_common.py +77 -0
- agentcore/logging/cdk_io_host.py +36 -0
- agentcore/logging/create_logger.py +107 -0
- agentcore/logging/dev_logger.py +63 -0
- agentcore/logging/exec_logger.py +159 -0
- agentcore/logging/invoke_logger.py +154 -0
- agentcore/logging/remove_logger.py +95 -0
- agentcore/operations/__init__.py +0 -0
- agentcore/operations/agent/__init__.py +0 -0
- agentcore/operations/agent/config_bundle_defaults.py +31 -0
- agentcore/operations/agent/generate/__init__.py +28 -0
- agentcore/operations/agent/generate/schema_mapper.py +319 -0
- agentcore/operations/agent/generate/types.py +172 -0
- agentcore/operations/agent/generate/write_agent_to_project.py +67 -0
- agentcore/operations/agent/import_/__init__.py +31 -0
- agentcore/operations/agent/import_/base_translator.py +449 -0
- agentcore/operations/agent/import_/constants.py +23 -0
- agentcore/operations/agent/import_/execute.py +127 -0
- agentcore/operations/agent/import_/langgraph_translator.py +294 -0
- agentcore/operations/agent/import_/pyproject_generator.py +73 -0
- agentcore/operations/agent/import_/strands_translator.py +289 -0
- agentcore/operations/config_bundle/__init__.py +1 -0
- agentcore/operations/config_bundle/bundle_name_variants.py +9 -0
- agentcore/operations/config_bundle/diff_versions.py +52 -0
- agentcore/operations/config_bundle/resolve_bundle.py +65 -0
- agentcore/operations/connectors/__init__.py +3 -0
- agentcore/operations/connectors/translators.py +63 -0
- agentcore/operations/dataset/__init__.py +21 -0
- agentcore/operations/dataset/delete.py +7 -0
- agentcore/operations/dataset/publish.py +16 -0
- agentcore/operations/dataset/pull.py +21 -0
- agentcore/operations/dataset/push.py +201 -0
- agentcore/operations/dataset/resolve_dataset.py +65 -0
- agentcore/operations/dataset/status.py +18 -0
- agentcore/operations/dataset/wait.py +25 -0
- agentcore/operations/deploy/__init__.py +152 -0
- agentcore/operations/deploy/backfill_vpc_id.py +90 -0
- agentcore/operations/deploy/change_detection.py +84 -0
- agentcore/operations/deploy/constants.py +58 -0
- agentcore/operations/deploy/dependency_sync.py +105 -0
- agentcore/operations/deploy/ensure_target.py +30 -0
- agentcore/operations/deploy/gateway_status.py +44 -0
- agentcore/operations/deploy/managed_memory_notice.py +36 -0
- agentcore/operations/deploy/payment_connector_authorization.py +106 -0
- agentcore/operations/deploy/post_deploy_datasets.py +96 -0
- agentcore/operations/deploy/post_deploy_knowledge_bases.py +104 -0
- agentcore/operations/deploy/post_deploy_observability.py +28 -0
- agentcore/operations/deploy/post_deploy_online_evals.py +60 -0
- agentcore/operations/deploy/pre_deploy_identity.py +505 -0
- agentcore/operations/deploy/preflight.py +385 -0
- agentcore/operations/deploy/region_override.py +45 -0
- agentcore/operations/deploy/teardown.py +153 -0
- agentcore/operations/dev/__init__.py +61 -0
- agentcore/operations/dev/_http.py +79 -0
- agentcore/operations/dev/_server.py +165 -0
- agentcore/operations/dev/codezip_dev_server.py +151 -0
- agentcore/operations/dev/config.py +128 -0
- agentcore/operations/dev/constants.py +9 -0
- agentcore/operations/dev/container_dev_server.py +237 -0
- agentcore/operations/dev/container_runtime.py +37 -0
- agentcore/operations/dev/dev_server.py +244 -0
- agentcore/operations/dev/gateway_env.py +25 -0
- agentcore/operations/dev/invoke.py +214 -0
- agentcore/operations/dev/invoke_a2a.py +204 -0
- agentcore/operations/dev/invoke_agui.py +88 -0
- agentcore/operations/dev/invoke_mcp.py +145 -0
- agentcore/operations/dev/invoke_types.py +30 -0
- agentcore/operations/dev/load_dev_env.py +26 -0
- agentcore/operations/dev/memory_env.py +19 -0
- agentcore/operations/dev/otel/__init__.py +5 -0
- agentcore/operations/dev/otel/collector.py +234 -0
- agentcore/operations/dev/otel/transforms.py +331 -0
- agentcore/operations/dev/payment_env.py +50 -0
- agentcore/operations/dev/server.py +28 -0
- agentcore/operations/dev/sse_transform.py +30 -0
- agentcore/operations/dev/utils.py +152 -0
- agentcore/operations/dev/web_ui/__init__.py +31 -0
- agentcore/operations/dev/web_ui/constants.py +25 -0
- agentcore/operations/dev/web_ui/handlers/__init__.py +36 -0
- agentcore/operations/dev/web_ui/handlers/_common.py +36 -0
- agentcore/operations/dev/web_ui/handlers/_deployed.py +37 -0
- agentcore/operations/dev/web_ui/handlers/a2a_proxy.py +37 -0
- agentcore/operations/dev/web_ui/handlers/cloudwatch_traces.py +71 -0
- agentcore/operations/dev/web_ui/handlers/harness_invocation.py +89 -0
- agentcore/operations/dev/web_ui/handlers/harness_utils.py +95 -0
- agentcore/operations/dev/web_ui/handlers/invocations.py +327 -0
- agentcore/operations/dev/web_ui/handlers/mcp_proxy.py +119 -0
- agentcore/operations/dev/web_ui/handlers/memory.py +84 -0
- agentcore/operations/dev/web_ui/handlers/resources.py +351 -0
- agentcore/operations/dev/web_ui/handlers/start.py +182 -0
- agentcore/operations/dev/web_ui/handlers/status.py +25 -0
- agentcore/operations/dev/web_ui/handlers/traces.py +50 -0
- agentcore/operations/dev/web_ui/run_web_ui.py +60 -0
- agentcore/operations/dev/web_ui/web_server.py +297 -0
- agentcore/operations/eval/__init__.py +8 -0
- agentcore/operations/eval/list_eval_runs.py +18 -0
- agentcore/operations/eval/logs_eval.py +119 -0
- agentcore/operations/eval/pause_resume.py +90 -0
- agentcore/operations/eval/run_eval.py +354 -0
- agentcore/operations/eval/shared/__init__.py +0 -0
- agentcore/operations/eval/shared/dataset_loader.py +68 -0
- agentcore/operations/eval/shared/dataset_session_provider.py +122 -0
- agentcore/operations/eval/shared/evaluator_runner.py +89 -0
- agentcore/operations/eval/shared/scenario_executor.py +71 -0
- agentcore/operations/eval/shared/span_collector.py +255 -0
- agentcore/operations/eval/storage.py +67 -0
- agentcore/operations/feedback/__init__.py +21 -0
- agentcore/operations/feedback/aperture_client.py +98 -0
- agentcore/operations/feedback/build_payload.py +97 -0
- agentcore/operations/feedback/constants.py +26 -0
- agentcore/operations/feedback/submit_feedback.py +150 -0
- agentcore/operations/fetch_access/__init__.py +36 -0
- agentcore/operations/fetch_access/_target.py +17 -0
- agentcore/operations/fetch_access/fetch_gateway_token.py +75 -0
- agentcore/operations/fetch_access/fetch_harness_token.py +72 -0
- agentcore/operations/fetch_access/fetch_runtime_token.py +76 -0
- agentcore/operations/fetch_access/list_agents.py +18 -0
- agentcore/operations/fetch_access/list_gateways.py +26 -0
- agentcore/operations/fetch_access/list_harnesses.py +23 -0
- agentcore/operations/fetch_access/oauth_token.py +162 -0
- agentcore/operations/fetch_access/types.py +34 -0
- agentcore/operations/harness/__init__.py +1 -0
- agentcore/operations/harness/orphan.py +84 -0
- agentcore/operations/harness/skill_utils.py +56 -0
- agentcore/operations/identity/__init__.py +33 -0
- agentcore/operations/identity/api_key_credential_provider.py +68 -0
- agentcore/operations/identity/oauth2_credential_provider.py +95 -0
- agentcore/operations/ingest/__init__.py +184 -0
- agentcore/operations/init/__init__.py +3 -0
- agentcore/operations/init/files.py +59 -0
- agentcore/operations/insights/__init__.py +21 -0
- agentcore/operations/insights/insights_storage.py +67 -0
- agentcore/operations/insights/run_insights.py +148 -0
- agentcore/operations/invoke/__init__.py +5 -0
- agentcore/operations/invoke/resolve_agent_context.py +85 -0
- agentcore/operations/jobs/__init__.py +38 -0
- agentcore/operations/jobs/ab_test/__init__.py +0 -0
- agentcore/operations/jobs/ab_test/build_options.py +126 -0
- agentcore/operations/jobs/ab_test/format.py +121 -0
- agentcore/operations/jobs/ab_test/handler.py +412 -0
- agentcore/operations/jobs/ab_test/promote.py +142 -0
- agentcore/operations/jobs/ab_test/resolve.py +221 -0
- agentcore/operations/jobs/batch_evaluation/__init__.py +0 -0
- agentcore/operations/jobs/batch_evaluation/build_source.py +68 -0
- agentcore/operations/jobs/batch_evaluation/dataset_phase1.py +95 -0
- agentcore/operations/jobs/batch_evaluation/format.py +58 -0
- agentcore/operations/jobs/batch_evaluation/handler.py +203 -0
- agentcore/operations/jobs/insights/__init__.py +0 -0
- agentcore/operations/jobs/insights/format.py +65 -0
- agentcore/operations/jobs/insights/handler.py +178 -0
- agentcore/operations/jobs/recommendation/__init__.py +0 -0
- agentcore/operations/jobs/recommendation/apply_to_bundle.py +76 -0
- agentcore/operations/jobs/recommendation/build_config.py +271 -0
- agentcore/operations/jobs/recommendation/fetch_session_spans.py +93 -0
- agentcore/operations/jobs/recommendation/format.py +77 -0
- agentcore/operations/jobs/recommendation/handler.py +331 -0
- agentcore/operations/jobs/shared/__init__.py +0 -0
- agentcore/operations/jobs/shared/constants.py +85 -0
- agentcore/operations/jobs/shared/engine.py +187 -0
- agentcore/operations/jobs/shared/format.py +104 -0
- agentcore/operations/jobs/shared/region.py +34 -0
- agentcore/operations/jobs/shared/resolve_agent_state.py +30 -0
- agentcore/operations/jobs/shared/storage.py +117 -0
- agentcore/operations/jobs/shared/wait.py +30 -0
- agentcore/operations/knowledge_base/__init__.py +33 -0
- agentcore/operations/knowledge_base/connector_config.py +105 -0
- agentcore/operations/knowledge_base/hydrate_data_sources.py +59 -0
- agentcore/operations/mcp/__init__.py +4 -0
- agentcore/operations/memory/__init__.py +13 -0
- agentcore/operations/memory/_records.py +72 -0
- agentcore/operations/memory/list_memory_records.py +45 -0
- agentcore/operations/memory/retrieve_memory_records.py +52 -0
- agentcore/operations/node/__init__.py +15 -0
- agentcore/operations/node/setup.py +36 -0
- agentcore/operations/python/__init__.py +17 -0
- agentcore/operations/python/setup.py +47 -0
- agentcore/operations/resolve_agent.py +159 -0
- agentcore/operations/session/__init__.py +86 -0
- agentcore/operations/traces/__init__.py +29 -0
- agentcore/operations/traces/get_trace.py +202 -0
- agentcore/operations/traces/insights_query.py +74 -0
- agentcore/operations/traces/list_traces.py +46 -0
- agentcore/operations/traces/trace_url.py +25 -0
- agentcore/operations/traces/types.py +55 -0
- agentcore/primitives/__init__.py +0 -0
- agentcore/primitives/_gateway_target_wizard.py +293 -0
- agentcore/primitives/_gateway_validation.py +442 -0
- agentcore/primitives/_harness_cli.py +557 -0
- agentcore/primitives/_harness_validation.py +163 -0
- agentcore/primitives/_harness_wizard.py +726 -0
- agentcore/primitives/_knowledge_base_wizard.py +259 -0
- agentcore/primitives/_payment_wizard.py +331 -0
- agentcore/primitives/_policy_form.py +160 -0
- agentcore/primitives/agent.py +817 -0
- agentcore/primitives/auth_utils.py +77 -0
- agentcore/primitives/base.py +178 -0
- agentcore/primitives/capacity_provider.py +501 -0
- agentcore/primitives/config_bundle.py +329 -0
- agentcore/primitives/credential.py +387 -0
- agentcore/primitives/credential_utils.py +45 -0
- agentcore/primitives/dataset.py +211 -0
- agentcore/primitives/deployed_gateways.py +34 -0
- agentcore/primitives/evaluator.py +909 -0
- agentcore/primitives/gateway.py +496 -0
- agentcore/primitives/gateway_target.py +988 -0
- agentcore/primitives/harness.py +706 -0
- agentcore/primitives/knowledge_base.py +477 -0
- agentcore/primitives/memory.py +387 -0
- agentcore/primitives/online_eval_config.py +365 -0
- agentcore/primitives/online_insights.py +275 -0
- agentcore/primitives/payment_connector.py +427 -0
- agentcore/primitives/payment_eligible.py +20 -0
- agentcore/primitives/payment_manager.py +605 -0
- agentcore/primitives/payment_validation.py +68 -0
- agentcore/primitives/policy.py +622 -0
- agentcore/primitives/policy_engine.py +358 -0
- agentcore/primitives/registry.py +56 -0
- agentcore/primitives/runtime_endpoint.py +361 -0
- agentcore/primitives/secret_flag_warning.py +17 -0
- agentcore/schema/__init__.py +14 -0
- agentcore/schema/_zod.py +395 -0
- agentcore/schema/constants.py +306 -0
- agentcore/schema/schemas/__init__.py +40 -0
- agentcore/schema/schemas/agent_env.py +545 -0
- agentcore/schema/schemas/agentcore_project.py +530 -0
- agentcore/schema/schemas/auth.py +286 -0
- agentcore/schema/schemas/aws_targets.py +72 -0
- agentcore/schema/schemas/connections.py +187 -0
- agentcore/schema/schemas/deployed_state.py +322 -0
- agentcore/schema/schemas/mcp.py +650 -0
- agentcore/schema/schemas/mcp_defs.py +54 -0
- agentcore/schema/schemas/primitives/__init__.py +52 -0
- agentcore/schema/schemas/primitives/ab_test.py +162 -0
- agentcore/schema/schemas/primitives/capacity_provider.py +214 -0
- agentcore/schema/schemas/primitives/config_bundle.py +48 -0
- agentcore/schema/schemas/primitives/dataset.py +55 -0
- agentcore/schema/schemas/primitives/evaluator.py +171 -0
- agentcore/schema/schemas/primitives/harness.py +710 -0
- agentcore/schema/schemas/primitives/knowledge_base.py +90 -0
- agentcore/schema/schemas/primitives/memory.py +113 -0
- agentcore/schema/schemas/primitives/online_eval_config.py +77 -0
- agentcore/schema/schemas/primitives/payment.py +114 -0
- agentcore/schema/schemas/primitives/policy.py +83 -0
- agentcore/schema/schemas/primitives/tags.py +50 -0
- agentcore/schema/schemas/zod_util.py +5 -0
- agentcore/schema/types/__init__.py +3 -0
- agentcore/schema/types/path.py +16 -0
- agentcore/templates/__init__.py +115 -0
- agentcore/templates/_handlebars.py +782 -0
- agentcore/templates/_js.py +164 -0
- agentcore/templates/base_renderer.py +107 -0
- agentcore/templates/cdk_renderer.py +129 -0
- agentcore/templates/evaluator_renderer.py +39 -0
- agentcore/templates/gateway_target_renderer.py +69 -0
- agentcore/templates/llm_context/README.md +16 -0
- agentcore/templates/llm_context/agentcore.ts +685 -0
- agentcore/templates/llm_context/aws-targets.ts +51 -0
- agentcore/templates/profiles.py +151 -0
- agentcore/templates/render.py +92 -0
- agentcore/templates/renderers.py +83 -0
- agentcore/templates/schema_assets.py +23 -0
- agentcore/templates/template_root.py +28 -0
- agentcore/templates/types.py +192 -0
- agentcore_cli-0.31.1.dist-info/METADATA +84 -0
- agentcore_cli-0.31.1.dist-info/RECORD +655 -0
- agentcore_cli-0.31.1.dist-info/WHEEL +4 -0
- agentcore_cli-0.31.1.dist-info/entry_points.txt +2 -0
- agentcore_cli-0.31.1.dist-info/licenses/LICENSE +175 -0
- agentcore_cli-0.31.1.dist-info/licenses/NOTICE +88 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""Port of operations/dev/invoke.ts: invoke the local HTTP agent (/invocations)."""
|
|
2
|
+
|
|
3
|
+
import codecs
|
|
4
|
+
import json
|
|
5
|
+
import re
|
|
6
|
+
import traceback
|
|
7
|
+
from collections.abc import Iterator
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from agentcore.lib.errors.types import DevServerConnectionError, DevServerError
|
|
11
|
+
from agentcore.operations.dev._http import fetch
|
|
12
|
+
from agentcore.operations.dev.invoke_types import InvokeStreamingOptions, SSELogger, log_to
|
|
13
|
+
from agentcore.operations.dev.utils import is_connection_error, sleep
|
|
14
|
+
|
|
15
|
+
MAX_RETRIES = 5
|
|
16
|
+
BASE_DELAY_MS = 500
|
|
17
|
+
_LINE_SPLIT = re.compile(r"\r?\n")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _js_string(value: Any) -> str:
|
|
21
|
+
if isinstance(value, str):
|
|
22
|
+
return value
|
|
23
|
+
if value is None:
|
|
24
|
+
return "null"
|
|
25
|
+
if isinstance(value, bool):
|
|
26
|
+
return "true" if value else "false"
|
|
27
|
+
if isinstance(value, (dict, list)):
|
|
28
|
+
return "[object Object]" if isinstance(value, dict) else ",".join(_js_string(v) for v in value)
|
|
29
|
+
return str(value)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def parse_sse_line(line: str) -> tuple[str | None, str | None]:
|
|
33
|
+
"""``(content, error)`` carried by one SSE ``data:`` line."""
|
|
34
|
+
if not line.startswith("data: "):
|
|
35
|
+
return None, None
|
|
36
|
+
raw = line[6:]
|
|
37
|
+
try:
|
|
38
|
+
parsed = json.loads(raw)
|
|
39
|
+
except ValueError:
|
|
40
|
+
return raw, None
|
|
41
|
+
if isinstance(parsed, str):
|
|
42
|
+
return parsed, None
|
|
43
|
+
if isinstance(parsed, dict):
|
|
44
|
+
if "error" in parsed:
|
|
45
|
+
return None, _js_string(parsed["error"])
|
|
46
|
+
if "text" in parsed:
|
|
47
|
+
return _js_string(parsed["text"]), None
|
|
48
|
+
event = parsed.get("event")
|
|
49
|
+
if isinstance(event, dict):
|
|
50
|
+
text = ((event.get("contentBlockDelta") or {}).get("delta") or {}).get("text")
|
|
51
|
+
if isinstance(text, str):
|
|
52
|
+
return text, None
|
|
53
|
+
return None, None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def parse_sse(text: str) -> str:
|
|
57
|
+
parts: list[str] = []
|
|
58
|
+
for line in text.split("\n"):
|
|
59
|
+
content, error = parse_sse_line(line)
|
|
60
|
+
if error:
|
|
61
|
+
return f"Error: {error}"
|
|
62
|
+
if content:
|
|
63
|
+
parts.append(content)
|
|
64
|
+
return "".join(parts) if parts else text
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def extract_result(text: str) -> str:
|
|
68
|
+
try:
|
|
69
|
+
parsed = json.loads(text)
|
|
70
|
+
except ValueError:
|
|
71
|
+
return text
|
|
72
|
+
if isinstance(parsed, dict) and "result" in parsed:
|
|
73
|
+
result = parsed["result"]
|
|
74
|
+
return result if isinstance(result, str) else json.dumps(result, indent=2, ensure_ascii=False)
|
|
75
|
+
return json.dumps(parsed, indent=2, ensure_ascii=False)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _request_headers(custom: dict[str, str] | None) -> dict[str, str]:
|
|
79
|
+
return {
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
"Accept": "text/event-stream",
|
|
82
|
+
"x-amzn-bedrock-agentcore-runtime-session-id": "local-dev-session",
|
|
83
|
+
**(custom or {}),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _stack(err: BaseException) -> str:
|
|
88
|
+
return "".join(traceback.format_exception(err)).rstrip() if err.__traceback__ else str(err)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _retry_loop_error(err: BaseException, attempt: int, logger: SSELogger | None) -> bool:
|
|
92
|
+
"""Shared catch block: True to retry; raises for HTTP and non-connection errors."""
|
|
93
|
+
if isinstance(err, DevServerError):
|
|
94
|
+
log_to(logger, "error", f"Server error ({err.status_code}): {err}")
|
|
95
|
+
raise err
|
|
96
|
+
if is_connection_error(err):
|
|
97
|
+
delay = BASE_DELAY_MS * 2**attempt
|
|
98
|
+
log_to(
|
|
99
|
+
logger,
|
|
100
|
+
"warn",
|
|
101
|
+
f"Connection failed (attempt {attempt + 1}/{MAX_RETRIES}): {err}. Retrying in {delay}ms...",
|
|
102
|
+
)
|
|
103
|
+
sleep(delay)
|
|
104
|
+
return True
|
|
105
|
+
log_to(logger, "error", f"Request failed: {_stack(err)}")
|
|
106
|
+
raise err
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _final_error(last: BaseException | None, logger: SSELogger | None, default: str) -> DevServerConnectionError:
|
|
110
|
+
final = DevServerConnectionError(str(last) if last else default)
|
|
111
|
+
final.__cause__ = last
|
|
112
|
+
log_to(logger, "error", f"Failed to connect after {MAX_RETRIES} attempts: {final}")
|
|
113
|
+
return final
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def invoke_agent_streaming(options: InvokeStreamingOptions | int, message: str | None = None) -> Iterator[str]:
|
|
117
|
+
"""Stream text chunks from the local agent's SSE response (falls back to plain JSON bodies)."""
|
|
118
|
+
if isinstance(options, int):
|
|
119
|
+
options = InvokeStreamingOptions(port=options, message=message or "")
|
|
120
|
+
port, logger = options.port, options.logger
|
|
121
|
+
last: BaseException | None = None
|
|
122
|
+
|
|
123
|
+
for attempt in range(MAX_RETRIES):
|
|
124
|
+
try:
|
|
125
|
+
res = fetch(
|
|
126
|
+
f"http://localhost:{port}/invocations",
|
|
127
|
+
method="POST",
|
|
128
|
+
headers=_request_headers(options.headers),
|
|
129
|
+
body=json.dumps({"prompt": options.message}),
|
|
130
|
+
)
|
|
131
|
+
if not res.ok:
|
|
132
|
+
raise DevServerError(res.status, res.text())
|
|
133
|
+
|
|
134
|
+
decoder = codecs.getincrementaldecoder("utf-8")(errors="replace")
|
|
135
|
+
buffer = ""
|
|
136
|
+
full = ""
|
|
137
|
+
yielded = False
|
|
138
|
+
for chunk in res.iter_chunks():
|
|
139
|
+
decoded = decoder.decode(chunk)
|
|
140
|
+
buffer += decoded
|
|
141
|
+
full += decoded
|
|
142
|
+
lines = _LINE_SPLIT.split(buffer)
|
|
143
|
+
buffer = lines.pop()
|
|
144
|
+
for line in lines:
|
|
145
|
+
if logger is not None and line.strip():
|
|
146
|
+
logger.log_sse_event(line)
|
|
147
|
+
content, error = parse_sse_line(line)
|
|
148
|
+
if error:
|
|
149
|
+
yield f"Error: {error}"
|
|
150
|
+
return
|
|
151
|
+
if content:
|
|
152
|
+
yield content
|
|
153
|
+
yielded = True
|
|
154
|
+
if buffer:
|
|
155
|
+
if logger is not None and buffer.strip():
|
|
156
|
+
logger.log_sse_event(buffer)
|
|
157
|
+
content, error = parse_sse_line(buffer)
|
|
158
|
+
if error:
|
|
159
|
+
yield f"Error: {error}"
|
|
160
|
+
return
|
|
161
|
+
if content:
|
|
162
|
+
yield content
|
|
163
|
+
yielded = True
|
|
164
|
+
if not yielded and full.strip():
|
|
165
|
+
yield extract_result(full.strip())
|
|
166
|
+
return
|
|
167
|
+
except Exception as err: # noqa: BLE001 - classified below, as upstream
|
|
168
|
+
last = err
|
|
169
|
+
_retry_loop_error(err, attempt, logger)
|
|
170
|
+
raise _final_error(last, logger, "Failed to connect to dev server after retries")
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def invoke_for_protocol(protocol: str, options: InvokeStreamingOptions) -> Iterator[str]:
|
|
174
|
+
"""Dispatch to the protocol-specific streaming invoke (MCP uses list/call tools instead)."""
|
|
175
|
+
if protocol == "MCP":
|
|
176
|
+
raise RuntimeError("Use listMcpTools/callMcpTool for MCP agents")
|
|
177
|
+
if protocol == "A2A":
|
|
178
|
+
from agentcore.operations.dev.invoke_a2a import invoke_a2a_streaming
|
|
179
|
+
|
|
180
|
+
yield from invoke_a2a_streaming(options)
|
|
181
|
+
elif protocol == "AGUI":
|
|
182
|
+
from agentcore.operations.dev.invoke_agui import invoke_agui_streaming
|
|
183
|
+
|
|
184
|
+
yield from invoke_agui_streaming(options)
|
|
185
|
+
else:
|
|
186
|
+
yield from invoke_agent_streaming(options)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def invoke_agent(options: InvokeStreamingOptions | int, message: str | None = None) -> str:
|
|
190
|
+
"""Non-streaming invoke: returns the combined SSE text or the extracted JSON result."""
|
|
191
|
+
if isinstance(options, int):
|
|
192
|
+
options = InvokeStreamingOptions(port=options, message=message or "")
|
|
193
|
+
port, logger = options.port, options.logger
|
|
194
|
+
last: BaseException | None = None
|
|
195
|
+
for attempt in range(MAX_RETRIES):
|
|
196
|
+
try:
|
|
197
|
+
res = fetch(
|
|
198
|
+
f"http://localhost:{port}/invocations",
|
|
199
|
+
method="POST",
|
|
200
|
+
headers=_request_headers(options.headers),
|
|
201
|
+
body=json.dumps({"prompt": options.message}),
|
|
202
|
+
)
|
|
203
|
+
if not res.ok:
|
|
204
|
+
raise DevServerError(res.status, res.text())
|
|
205
|
+
text = res.text()
|
|
206
|
+
if not text:
|
|
207
|
+
return "(empty response)"
|
|
208
|
+
if "data: " in text:
|
|
209
|
+
return parse_sse(text)
|
|
210
|
+
return extract_result(text)
|
|
211
|
+
except Exception as err: # noqa: BLE001 - classified below, as upstream
|
|
212
|
+
last = err
|
|
213
|
+
_retry_loop_error(err, attempt, logger)
|
|
214
|
+
raise _final_error(last, logger, "Failed to connect to dev server after retries")
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""Port of operations/dev/invoke-a2a.ts: local A2A JSON-RPC invoke + agent card."""
|
|
2
|
+
|
|
3
|
+
import codecs
|
|
4
|
+
import itertools
|
|
5
|
+
import json
|
|
6
|
+
import uuid
|
|
7
|
+
from collections.abc import Callable, Iterator
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from agentcore.lib.errors.types import DevServerConnectionError, DevServerError
|
|
11
|
+
from agentcore.operations.dev._http import LocalResponse, fetch
|
|
12
|
+
from agentcore.operations.dev.invoke import BASE_DELAY_MS, MAX_RETRIES, _final_error, _retry_loop_error
|
|
13
|
+
from agentcore.operations.dev.invoke_types import InvokeStreamingOptions, SSELogger, log_to
|
|
14
|
+
from agentcore.operations.dev.utils import is_connection_error, sleep
|
|
15
|
+
|
|
16
|
+
_request_ids = itertools.count(1)
|
|
17
|
+
|
|
18
|
+
A2AAgentCard = dict[str, Any]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def fetch_a2a_agent_card(port: int, logger: SSELogger | None = None) -> A2AAgentCard | None:
|
|
22
|
+
"""Fetch /.well-known/agent-card.json, falling back to the v0.3 /.well-known/agent.json."""
|
|
23
|
+
for attempt in range(MAX_RETRIES):
|
|
24
|
+
try:
|
|
25
|
+
for path in ("/.well-known/agent-card.json", "/.well-known/agent.json"):
|
|
26
|
+
res = fetch(f"http://localhost:{port}{path}", headers={"Accept": "application/json"})
|
|
27
|
+
if not res.ok:
|
|
28
|
+
res.close()
|
|
29
|
+
if res.status == 404 and path == "/.well-known/agent-card.json":
|
|
30
|
+
continue
|
|
31
|
+
log_to(logger, "warn", f"Agent card not available ({res.status})")
|
|
32
|
+
return None
|
|
33
|
+
card = res.json()
|
|
34
|
+
log_to(logger, "system", f"A2A agent card: {(card or {}).get('name') or 'unnamed'}")
|
|
35
|
+
return card
|
|
36
|
+
except Exception as err: # noqa: BLE001 - retried or reported, as upstream
|
|
37
|
+
if is_connection_error(err) and attempt < MAX_RETRIES - 1:
|
|
38
|
+
sleep(BASE_DELAY_MS * 2**attempt)
|
|
39
|
+
continue
|
|
40
|
+
log_to(logger, "warn", f"Failed to fetch agent card: {err}")
|
|
41
|
+
return None
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _target(event: dict[str, Any]) -> dict[str, Any]:
|
|
46
|
+
result = event.get("result")
|
|
47
|
+
return result if isinstance(result, dict) else event
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def is_status_update_event(event: dict[str, Any]) -> bool:
|
|
51
|
+
return _target(event).get("kind") == "status-update"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _parts_text(parts: Any) -> str | None:
|
|
55
|
+
if not parts:
|
|
56
|
+
return None
|
|
57
|
+
texts = [
|
|
58
|
+
p["text"]
|
|
59
|
+
for p in parts
|
|
60
|
+
if isinstance(p, dict) and (p.get("kind") == "text" or p.get("type") == "text") and p.get("text")
|
|
61
|
+
]
|
|
62
|
+
return "".join(texts) if texts else None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def extract_task_text(result: dict[str, Any]) -> str | None:
|
|
66
|
+
"""Text from a full Task result (artifacts first, then status message)."""
|
|
67
|
+
artifacts = result.get("artifacts")
|
|
68
|
+
if artifacts:
|
|
69
|
+
texts = [t for a in artifacts if (t := _parts_text((a or {}).get("parts")))]
|
|
70
|
+
if texts:
|
|
71
|
+
return "\n".join(texts)
|
|
72
|
+
message = ((result.get("status") or {}) if isinstance(result.get("status"), dict) else {}).get("message")
|
|
73
|
+
if isinstance(message, dict) and message.get("parts"):
|
|
74
|
+
return _parts_text(message["parts"])
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def extract_sse_event_text(event: dict[str, Any], streamed_from_status: bool = False) -> str | None:
|
|
79
|
+
"""Displayable text of an A2A SSE event (artifact-update text is skipped once status streamed it)."""
|
|
80
|
+
target = _target(event)
|
|
81
|
+
kind = target.get("kind")
|
|
82
|
+
if kind == "artifact-update":
|
|
83
|
+
if streamed_from_status:
|
|
84
|
+
return None
|
|
85
|
+
return _parts_text((target.get("artifact") or {}).get("parts"))
|
|
86
|
+
if kind == "status-update":
|
|
87
|
+
message = (target.get("status") or {}).get("message")
|
|
88
|
+
if isinstance(message, dict) and message.get("parts"):
|
|
89
|
+
return _parts_text(message["parts"])
|
|
90
|
+
return None
|
|
91
|
+
return extract_task_text(target)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _handle_sse_event(event: dict[str, Any], on_status: Callable[[str], None] | None) -> None:
|
|
95
|
+
if on_status is None:
|
|
96
|
+
return
|
|
97
|
+
target = _target(event)
|
|
98
|
+
if target.get("kind") != "status-update":
|
|
99
|
+
return
|
|
100
|
+
state = (target.get("status") or {}).get("state")
|
|
101
|
+
if state:
|
|
102
|
+
on_status(state)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def _parse_a2a_sse_stream(
|
|
106
|
+
res: LocalResponse, logger: SSELogger | None, on_status: Callable[[str], None] | None
|
|
107
|
+
) -> Iterator[str]:
|
|
108
|
+
decoder = codecs.getincrementaldecoder("utf-8")(errors="replace")
|
|
109
|
+
buffer = ""
|
|
110
|
+
streamed_from_status = False
|
|
111
|
+
for chunk in res.iter_chunks():
|
|
112
|
+
buffer += decoder.decode(chunk)
|
|
113
|
+
lines = buffer.split("\n")
|
|
114
|
+
buffer = lines.pop()
|
|
115
|
+
for line in lines:
|
|
116
|
+
if not line.startswith("data: "):
|
|
117
|
+
continue
|
|
118
|
+
data = line[6:].strip()
|
|
119
|
+
if not data:
|
|
120
|
+
continue
|
|
121
|
+
if logger is not None:
|
|
122
|
+
logger.log_sse_event(line)
|
|
123
|
+
try:
|
|
124
|
+
event = json.loads(data)
|
|
125
|
+
if not isinstance(event, dict):
|
|
126
|
+
raise ValueError("not an object")
|
|
127
|
+
_handle_sse_event(event, on_status)
|
|
128
|
+
text = extract_sse_event_text(event, streamed_from_status)
|
|
129
|
+
except (ValueError, AttributeError, TypeError):
|
|
130
|
+
yield data
|
|
131
|
+
continue
|
|
132
|
+
if text:
|
|
133
|
+
if is_status_update_event(event):
|
|
134
|
+
streamed_from_status = True
|
|
135
|
+
yield text
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def invoke_a2a_streaming(options: InvokeStreamingOptions) -> Iterator[str]:
|
|
139
|
+
"""JSON-RPC ``message/stream`` (SSE) with a non-streaming JSON fallback."""
|
|
140
|
+
port, logger = options.port, options.logger
|
|
141
|
+
last: BaseException | None = None
|
|
142
|
+
for attempt in range(MAX_RETRIES):
|
|
143
|
+
try:
|
|
144
|
+
body = {
|
|
145
|
+
"jsonrpc": "2.0",
|
|
146
|
+
"id": next(_request_ids),
|
|
147
|
+
"method": "message/stream",
|
|
148
|
+
"params": {
|
|
149
|
+
"message": {
|
|
150
|
+
"messageId": str(uuid.uuid4()),
|
|
151
|
+
"role": "user",
|
|
152
|
+
"parts": [{"kind": "text", "text": options.message}],
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
}
|
|
156
|
+
log_to(logger, "system", f"A2A message/stream: {options.message}")
|
|
157
|
+
res = fetch(
|
|
158
|
+
f"http://localhost:{port}/",
|
|
159
|
+
method="POST",
|
|
160
|
+
headers={"Content-Type": "application/json", "Accept": "text/event-stream", **(options.headers or {})},
|
|
161
|
+
body=json.dumps(body),
|
|
162
|
+
)
|
|
163
|
+
if not res.ok:
|
|
164
|
+
raise DevServerError(res.status, res.text())
|
|
165
|
+
|
|
166
|
+
if "text/event-stream" in (res.header("content-type") or ""):
|
|
167
|
+
yield from _parse_a2a_sse_stream(res, logger, options.on_status)
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
text = res.text()
|
|
171
|
+
if logger is not None:
|
|
172
|
+
logger.log_sse_event(text)
|
|
173
|
+
try:
|
|
174
|
+
parsed = json.loads(text)
|
|
175
|
+
if not isinstance(parsed, dict):
|
|
176
|
+
raise ValueError("not an object")
|
|
177
|
+
except ValueError:
|
|
178
|
+
yield text
|
|
179
|
+
return
|
|
180
|
+
if parsed.get("error"):
|
|
181
|
+
rpc_error = parsed["error"] if isinstance(parsed["error"], dict) else {}
|
|
182
|
+
raise DevServerError(rpc_error.get("code") or 500, rpc_error.get("message") or "A2A RPC error")
|
|
183
|
+
result = parsed.get("result")
|
|
184
|
+
if result:
|
|
185
|
+
task_text = extract_task_text(result) if isinstance(result, dict) else None
|
|
186
|
+
yield task_text or json.dumps(result, indent=2, ensure_ascii=False)
|
|
187
|
+
else:
|
|
188
|
+
yield text
|
|
189
|
+
return
|
|
190
|
+
except Exception as err: # noqa: BLE001 - classified by the shared retry handler
|
|
191
|
+
last = err
|
|
192
|
+
_retry_loop_error(err, attempt, logger)
|
|
193
|
+
raise _final_error(last, logger, "Failed to connect to A2A server after retries")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
__all__ = [
|
|
197
|
+
"A2AAgentCard",
|
|
198
|
+
"DevServerConnectionError",
|
|
199
|
+
"extract_sse_event_text",
|
|
200
|
+
"extract_task_text",
|
|
201
|
+
"fetch_a2a_agent_card",
|
|
202
|
+
"invoke_a2a_streaming",
|
|
203
|
+
"is_status_update_event",
|
|
204
|
+
]
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Port of operations/dev/invoke-agui.ts: local AG-UI invoke (RunAgentInput over SSE)."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import uuid
|
|
5
|
+
from collections.abc import Iterator
|
|
6
|
+
|
|
7
|
+
from agentcore.aws.agui_parser import parse_agui_sse_stream
|
|
8
|
+
from agentcore.aws.agui_types import AguiEventType
|
|
9
|
+
from agentcore.lib.errors.types import DevServerError
|
|
10
|
+
from agentcore.operations.dev._http import fetch
|
|
11
|
+
from agentcore.operations.dev.invoke import MAX_RETRIES, _final_error, _retry_loop_error
|
|
12
|
+
from agentcore.operations.dev.invoke_types import InvokeStreamingOptions, log_to
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def invoke_agui_streaming(options: InvokeStreamingOptions) -> Iterator[str]:
|
|
16
|
+
port, logger = options.port, options.logger
|
|
17
|
+
last: BaseException | None = None
|
|
18
|
+
streaming = False
|
|
19
|
+
|
|
20
|
+
for attempt in range(MAX_RETRIES):
|
|
21
|
+
try:
|
|
22
|
+
body = {
|
|
23
|
+
"threadId": options.thread_id or str(uuid.uuid4()),
|
|
24
|
+
"runId": str(uuid.uuid4()),
|
|
25
|
+
"messages": [{"id": str(uuid.uuid4()), "role": "user", "content": options.message}],
|
|
26
|
+
"tools": [],
|
|
27
|
+
"context": [],
|
|
28
|
+
"state": {},
|
|
29
|
+
"forwardedProps": {},
|
|
30
|
+
}
|
|
31
|
+
log_to(logger, "system", f"AGUI invoke: {options.message}")
|
|
32
|
+
res = fetch(
|
|
33
|
+
f"http://localhost:{port}/invocations",
|
|
34
|
+
method="POST",
|
|
35
|
+
headers={"Content-Type": "application/json", "Accept": "text/event-stream", **(options.headers or {})},
|
|
36
|
+
body=json.dumps(body),
|
|
37
|
+
)
|
|
38
|
+
if not res.ok:
|
|
39
|
+
raise DevServerError(res.status, res.text())
|
|
40
|
+
|
|
41
|
+
streams = parse_agui_sse_stream(res.iter_chunks(), logger=logger, single_consumer=True)
|
|
42
|
+
yielded = False
|
|
43
|
+
tool_calls: list[dict[str, str]] = []
|
|
44
|
+
active_id = active_name = active_args = ""
|
|
45
|
+
|
|
46
|
+
for event in streams.event_stream:
|
|
47
|
+
etype = event.get("type")
|
|
48
|
+
if etype in (AguiEventType.TEXT_MESSAGE_CONTENT, AguiEventType.TEXT_MESSAGE_CHUNK):
|
|
49
|
+
delta = event.get("delta")
|
|
50
|
+
if delta:
|
|
51
|
+
streaming = True
|
|
52
|
+
yield delta
|
|
53
|
+
yielded = True
|
|
54
|
+
elif etype == AguiEventType.TOOL_CALL_START:
|
|
55
|
+
active_id = event.get("toolCallId") or ""
|
|
56
|
+
active_name = event.get("toolCallName") or ""
|
|
57
|
+
active_args = ""
|
|
58
|
+
elif etype == AguiEventType.TOOL_CALL_ARGS:
|
|
59
|
+
if event.get("delta"):
|
|
60
|
+
active_args += event["delta"]
|
|
61
|
+
elif etype == AguiEventType.TOOL_CALL_END:
|
|
62
|
+
if active_name:
|
|
63
|
+
tool_calls.append({"id": active_id, "name": active_name, "args": active_args})
|
|
64
|
+
active_id = active_name = active_args = ""
|
|
65
|
+
elif etype == AguiEventType.TOOL_CALL_RESULT:
|
|
66
|
+
content = event.get("content")
|
|
67
|
+
matching = next((tc for tc in tool_calls if tc["id"] == (event.get("toolCallId") or "")), None)
|
|
68
|
+
if matching and content:
|
|
69
|
+
rendered = content if isinstance(content, str) else json.dumps(content, separators=(",", ":"))
|
|
70
|
+
matching["args"] = f"{matching['args']} → {rendered}"
|
|
71
|
+
elif etype == AguiEventType.RUN_ERROR:
|
|
72
|
+
message = event.get("message") if "message" in event else "Unknown AGUI error"
|
|
73
|
+
yield f"Error: {message}"
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
if not yielded and tool_calls:
|
|
77
|
+
for tc in tool_calls:
|
|
78
|
+
yield f"[Tool: {tc['name']}({tc['args']})]\n"
|
|
79
|
+
yielded = True
|
|
80
|
+
if not yielded:
|
|
81
|
+
yield "(no content in AGUI response)"
|
|
82
|
+
return
|
|
83
|
+
except Exception as err:
|
|
84
|
+
last = err
|
|
85
|
+
if streaming:
|
|
86
|
+
raise
|
|
87
|
+
_retry_loop_error(err, attempt, logger)
|
|
88
|
+
raise _final_error(last, logger, "Failed to connect to AGUI server after retries")
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Port of operations/dev/invoke-mcp.ts: list/call tools on a local MCP server."""
|
|
2
|
+
|
|
3
|
+
import itertools
|
|
4
|
+
import json
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from agentcore.lib.errors.types import DevServerError
|
|
9
|
+
from agentcore.lib.utils.json_rpc import parse_json_rpc_response
|
|
10
|
+
from agentcore.operations.dev._http import fetch
|
|
11
|
+
from agentcore.operations.dev.invoke import MAX_RETRIES, _final_error, _retry_loop_error
|
|
12
|
+
from agentcore.operations.dev.invoke_types import SSELogger, log_to
|
|
13
|
+
|
|
14
|
+
_request_ids = itertools.count(1)
|
|
15
|
+
|
|
16
|
+
McpTool = dict[str, Any]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class McpToolsResult:
|
|
21
|
+
tools: list[McpTool] = field(default_factory=list)
|
|
22
|
+
session_id: str | None = None
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _post(port: int, headers: dict[str, str], body: dict[str, Any]): # type: ignore[no-untyped-def]
|
|
26
|
+
return fetch(f"http://localhost:{port}/mcp", method="POST", headers=headers, body=json.dumps(body))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def list_mcp_tools(
|
|
30
|
+
port: int, logger: SSELogger | None = None, custom_headers: dict[str, str] | None = None
|
|
31
|
+
) -> McpToolsResult:
|
|
32
|
+
"""initialize + notifications/initialized + tools/list; returns tools and the MCP session id."""
|
|
33
|
+
last: BaseException | None = None
|
|
34
|
+
for attempt in range(MAX_RETRIES):
|
|
35
|
+
try:
|
|
36
|
+
init_body = {
|
|
37
|
+
"jsonrpc": "2.0",
|
|
38
|
+
"id": next(_request_ids),
|
|
39
|
+
"method": "initialize",
|
|
40
|
+
"params": {
|
|
41
|
+
"protocolVersion": "2025-03-26",
|
|
42
|
+
"capabilities": {},
|
|
43
|
+
"clientInfo": {"name": "agentcore-cli", "version": "1.0.0"},
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
log_to(logger, "system", "MCP initialize")
|
|
47
|
+
init_res = _post(
|
|
48
|
+
port,
|
|
49
|
+
{
|
|
50
|
+
"Content-Type": "application/json",
|
|
51
|
+
"Accept": "application/json, text/event-stream",
|
|
52
|
+
**(custom_headers or {}),
|
|
53
|
+
},
|
|
54
|
+
init_body,
|
|
55
|
+
)
|
|
56
|
+
if not init_res.ok:
|
|
57
|
+
raise DevServerError(init_res.status, init_res.text())
|
|
58
|
+
session_id = init_res.header("mcp-session-id")
|
|
59
|
+
init_text = init_res.text()
|
|
60
|
+
if logger is not None:
|
|
61
|
+
logger.log_sse_event(init_text)
|
|
62
|
+
|
|
63
|
+
session_headers = {"Content-Type": "application/json", **(custom_headers or {})}
|
|
64
|
+
if session_id:
|
|
65
|
+
session_headers["mcp-session-id"] = session_id
|
|
66
|
+
_post(port, session_headers, {"jsonrpc": "2.0", "method": "notifications/initialized"}).close()
|
|
67
|
+
|
|
68
|
+
log_to(logger, "system", "MCP tools/list")
|
|
69
|
+
list_res = _post(
|
|
70
|
+
port,
|
|
71
|
+
{
|
|
72
|
+
"Content-Type": "application/json",
|
|
73
|
+
"Accept": "application/json, text/event-stream",
|
|
74
|
+
**session_headers,
|
|
75
|
+
},
|
|
76
|
+
{"jsonrpc": "2.0", "id": next(_request_ids), "method": "tools/list", "params": {}},
|
|
77
|
+
)
|
|
78
|
+
if not list_res.ok:
|
|
79
|
+
raise DevServerError(list_res.status, list_res.text())
|
|
80
|
+
list_text = list_res.text()
|
|
81
|
+
if logger is not None:
|
|
82
|
+
logger.log_sse_event(list_text)
|
|
83
|
+
parsed = parse_json_rpc_response(list_text)
|
|
84
|
+
tools = ((parsed.get("result") or {}) if isinstance(parsed.get("result"), dict) else {}).get("tools") or []
|
|
85
|
+
return McpToolsResult(
|
|
86
|
+
tools=[
|
|
87
|
+
{
|
|
88
|
+
k: v
|
|
89
|
+
for k, v in {
|
|
90
|
+
"name": t.get("name"),
|
|
91
|
+
"description": t.get("description"),
|
|
92
|
+
"inputSchema": t.get("inputSchema"),
|
|
93
|
+
}.items()
|
|
94
|
+
if v is not None
|
|
95
|
+
}
|
|
96
|
+
for t in tools
|
|
97
|
+
],
|
|
98
|
+
session_id=session_id or None,
|
|
99
|
+
)
|
|
100
|
+
except Exception as err: # noqa: BLE001 - classified by the shared retry handler
|
|
101
|
+
last = err
|
|
102
|
+
_retry_loop_error(err, attempt, logger)
|
|
103
|
+
raise _final_error(last, logger, "Failed to connect to MCP server after retries")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def call_mcp_tool(
|
|
107
|
+
port: int,
|
|
108
|
+
tool_name: str,
|
|
109
|
+
args: dict[str, Any],
|
|
110
|
+
session_id: str | None = None,
|
|
111
|
+
logger: SSELogger | None = None,
|
|
112
|
+
custom_headers: dict[str, str] | None = None,
|
|
113
|
+
) -> str:
|
|
114
|
+
"""tools/call; returns the concatenated text content (or the pretty-printed result)."""
|
|
115
|
+
body = {
|
|
116
|
+
"jsonrpc": "2.0",
|
|
117
|
+
"id": next(_request_ids),
|
|
118
|
+
"method": "tools/call",
|
|
119
|
+
"params": {"name": tool_name, "arguments": args},
|
|
120
|
+
}
|
|
121
|
+
log_to(logger, "system", f"MCP tools/call: {tool_name}({json.dumps(args, separators=(',', ':'))})")
|
|
122
|
+
headers = {
|
|
123
|
+
"Content-Type": "application/json",
|
|
124
|
+
"Accept": "application/json, text/event-stream",
|
|
125
|
+
**(custom_headers or {}),
|
|
126
|
+
}
|
|
127
|
+
if session_id:
|
|
128
|
+
headers["mcp-session-id"] = session_id
|
|
129
|
+
res = _post(port, headers, body)
|
|
130
|
+
if not res.ok:
|
|
131
|
+
raise DevServerError(res.status, res.text())
|
|
132
|
+
text = res.text()
|
|
133
|
+
if logger is not None:
|
|
134
|
+
logger.log_sse_event(text)
|
|
135
|
+
parsed = parse_json_rpc_response(text)
|
|
136
|
+
if parsed.get("error"):
|
|
137
|
+
rpc_error = parsed["error"] if isinstance(parsed["error"], dict) else {}
|
|
138
|
+
raise RuntimeError(rpc_error.get("message") or f"MCP error (code {rpc_error.get('code')})")
|
|
139
|
+
result = parsed.get("result")
|
|
140
|
+
content = result.get("content") if isinstance(result, dict) else None
|
|
141
|
+
if content:
|
|
142
|
+
texts = [item["text"] for item in content if isinstance(item, dict) and "text" in item]
|
|
143
|
+
if texts:
|
|
144
|
+
return "".join(texts)
|
|
145
|
+
return json.dumps(result, indent=2, ensure_ascii=False)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Port of operations/dev/invoke-types.ts."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Protocol
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SSELogger(Protocol):
|
|
9
|
+
"""Logger for SSE events; ``log(level, message)`` is optional (checked with getattr)."""
|
|
10
|
+
|
|
11
|
+
def log_sse_event(self, raw_line: str) -> None: ...
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class InvokeStreamingOptions:
|
|
16
|
+
port: int
|
|
17
|
+
message: str
|
|
18
|
+
logger: SSELogger | None = None
|
|
19
|
+
on_status: Callable[[str], None] | None = None
|
|
20
|
+
"""A2A task status updates (e.g. 'working', 'input-required')."""
|
|
21
|
+
headers: dict[str, str] | None = None
|
|
22
|
+
thread_id: str | None = None
|
|
23
|
+
"""Persistent AGUI thread ID for multi-turn conversations."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def log_to(logger: object | None, level: str, message: str) -> None:
|
|
27
|
+
"""Call ``logger.log(level, message)`` when the logger has one (``logger?.log?.(...)``)."""
|
|
28
|
+
log = getattr(logger, "log", None) if logger is not None else None
|
|
29
|
+
if callable(log):
|
|
30
|
+
log(level, message)
|