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,909 @@
|
|
|
1
|
+
"""Custom evaluator add/remove (port of src/cli/primitives/EvaluatorPrimitive.ts).
|
|
2
|
+
|
|
3
|
+
Also hosts the evaluator wizard constants from tui/screens/evaluator/types.ts (rating scale
|
|
4
|
+
presets, level placeholders, model options) since the flags and the prompts share them.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import math
|
|
9
|
+
import os
|
|
10
|
+
import re
|
|
11
|
+
import shutil
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
import typer
|
|
16
|
+
from pydantic import TypeAdapter
|
|
17
|
+
from pydantic import ValidationError as PydanticValidationError
|
|
18
|
+
|
|
19
|
+
from agentcore.cli import interactive
|
|
20
|
+
from agentcore.cli.errors import get_error_message
|
|
21
|
+
from agentcore.cli.naming import generate_unique_name
|
|
22
|
+
from agentcore.cli.run_command import run_cli_command
|
|
23
|
+
from agentcore.lib import ConflictError, ResourceNotFoundError, find_config_root, serialize_result
|
|
24
|
+
from agentcore.lib.errors.types import to_error
|
|
25
|
+
from agentcore.lib.result import Err, Ok
|
|
26
|
+
from agentcore.lib.schemas.io.config_io import to_jsonable
|
|
27
|
+
from agentcore.operations.jobs.shared.format import parse_int
|
|
28
|
+
from agentcore.primitives.base import BasePrimitive, RemovableResource, RemovalPreview, SchemaChange, emit_json
|
|
29
|
+
from agentcore.schema import EVALUATION_LEVELS, EvaluatorModelId, EvaluatorName, is_valid_kms_key_arn
|
|
30
|
+
from agentcore.schema.schemas.primitives.evaluator import is_valid_bedrock_model_id
|
|
31
|
+
from agentcore.templates import render_code_based_evaluator_template, render_third_party_evaluator_template
|
|
32
|
+
|
|
33
|
+
# ============================================================================
|
|
34
|
+
# Third-party library registry
|
|
35
|
+
# ============================================================================
|
|
36
|
+
|
|
37
|
+
THIRD_PARTY_EVALUATOR_LIBRARIES: dict[str, dict[str, Any]] = {
|
|
38
|
+
"deepeval": {
|
|
39
|
+
"templateDir": "deepeval-lambda",
|
|
40
|
+
"defaultTimeoutSeconds": 300,
|
|
41
|
+
"warnings": [
|
|
42
|
+
{
|
|
43
|
+
"metrics": {
|
|
44
|
+
"FaithfulnessMetric",
|
|
45
|
+
"HallucinationMetric",
|
|
46
|
+
"ContextualRelevancyMetric",
|
|
47
|
+
"ContextualPrecisionMetric",
|
|
48
|
+
"ContextualRecallMetric",
|
|
49
|
+
},
|
|
50
|
+
"message": "requires retrieval_context from tool-role messages. "
|
|
51
|
+
"If your agent has no tool calls, the evaluator will return MISSING_REQUIRED_FIELD at runtime.",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"metrics": {"ContextualPrecisionMetric", "ContextualRecallMetric"},
|
|
55
|
+
"message": "requires expected_output via evaluationReferenceInputs. "
|
|
56
|
+
"Caller must provide referenceInputs when invoking the Evaluate API.",
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
"autoevals": {
|
|
61
|
+
"templateDir": "autoevals-lambda",
|
|
62
|
+
"defaultTimeoutSeconds": 60,
|
|
63
|
+
"warnings": [
|
|
64
|
+
{
|
|
65
|
+
"metrics": {"Factuality", "ClosedQA"},
|
|
66
|
+
"message": "requires expected_output via evaluationReferenceInputs. "
|
|
67
|
+
"Caller must provide referenceInputs when invoking the Evaluate API.",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"metrics": {"SQL"},
|
|
71
|
+
"message": "requires expected_output (reference SQL) via evaluationReferenceInputs. "
|
|
72
|
+
"Caller must provide referenceInputs when invoking the Evaluate API.",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
SUPPORTED_LIBRARIES = list(THIRD_PARTY_EVALUATOR_LIBRARIES)
|
|
78
|
+
MODEL_PROVIDERS = ("openai", "bedrock")
|
|
79
|
+
|
|
80
|
+
DEFAULT_CODE_ENTRYPOINT = "lambda_function.handler"
|
|
81
|
+
DEFAULT_CODE_TIMEOUT = 60
|
|
82
|
+
_KWARG_NAME = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
|
|
83
|
+
_LAMBDA_ARN = re.compile(r"^arn:aws[a-z-]*:lambda:[a-z0-9-]+:\d{12}:function:.+$")
|
|
84
|
+
KMS_ARN_ERROR = (
|
|
85
|
+
"--kms-key-arn must be a valid KMS key ARN "
|
|
86
|
+
"(e.g. arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012)"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# ============================================================================
|
|
90
|
+
# Wizard constants (tui/screens/evaluator/types.ts)
|
|
91
|
+
# ============================================================================
|
|
92
|
+
|
|
93
|
+
EVALUATOR_TYPE_OPTIONS = (
|
|
94
|
+
("code-based", "Code-based (custom Lambda function)", "Write custom Python code for evaluation logic"),
|
|
95
|
+
("llm-as-a-judge", "LLM-as-a-Judge (model-based)", "Use a foundation model to evaluate quality"),
|
|
96
|
+
)
|
|
97
|
+
CODE_BASED_TYPE_OPTIONS = (
|
|
98
|
+
("managed", "Create new (CLI scaffolds and deploys the Lambda for you)", "CLI scaffolds code and deploys Lambda"),
|
|
99
|
+
("external", "Existing Lambda ARN (bring your own)", "Use an existing Lambda function"),
|
|
100
|
+
)
|
|
101
|
+
EVALUATION_LEVEL_OPTIONS = (
|
|
102
|
+
("SESSION", "Session", "Overall quality across an entire conversation"),
|
|
103
|
+
("TRACE", "Trace", "Per-turn accuracy of individual agent responses"),
|
|
104
|
+
("TOOL_CALL", "Tool Call", "Correctness of individual tool selections and usage"),
|
|
105
|
+
)
|
|
106
|
+
DEFAULT_MODEL = "us.anthropic.claude-sonnet-4-5-20250929-v1:0"
|
|
107
|
+
DEFAULT_OPENAI_MODEL = "openai.gpt-5.4"
|
|
108
|
+
CUSTOM_MODEL_ID = "__custom__"
|
|
109
|
+
EVALUATOR_MODEL_PROVIDER_OPTIONS = (
|
|
110
|
+
("Bedrock", "Amazon Bedrock", "Use the Bedrock Converse API"),
|
|
111
|
+
("OpenResponses", "OpenAI on Bedrock", "Use the OpenResponses API through Bedrock Mantle"),
|
|
112
|
+
)
|
|
113
|
+
BEDROCK_EVALUATOR_MODEL_OPTIONS = (
|
|
114
|
+
("us.anthropic.claude-sonnet-4-5-20250929-v1:0", "Claude Sonnet 4.5", "Recommended — balanced speed and accuracy"),
|
|
115
|
+
(
|
|
116
|
+
"global.anthropic.claude-opus-4-5-20251101-v1:0",
|
|
117
|
+
"Claude Opus 4.5",
|
|
118
|
+
"Most capable — best for complex evaluations",
|
|
119
|
+
),
|
|
120
|
+
("us.anthropic.claude-haiku-4-5-20251001-v1:0", "Claude Haiku 4.5", "Fastest — good for high-volume evaluations"),
|
|
121
|
+
("us.amazon.nova-pro-v1:0", "Amazon Nova Pro", "Amazon foundation model — strong reasoning"),
|
|
122
|
+
("us.amazon.nova-lite-v1:0", "Amazon Nova Lite", "Amazon foundation model — fast and cost-effective"),
|
|
123
|
+
(CUSTOM_MODEL_ID, "Other", "Enter a custom Bedrock model ID or ARN"),
|
|
124
|
+
)
|
|
125
|
+
OPENAI_EVALUATOR_MODEL_OPTIONS = (
|
|
126
|
+
("openai.gpt-5.4", "GPT-5.4", "Recommended — high-quality reasoning and evaluation"),
|
|
127
|
+
("openai.gpt-5.5", "GPT-5.5", "Most capable OpenAI model"),
|
|
128
|
+
("openai.gpt-oss-120b", "GPT OSS 120B", "Open-weight model for complex evaluations"),
|
|
129
|
+
("openai.gpt-oss-20b", "GPT OSS 20B", "Open-weight model for faster evaluations"),
|
|
130
|
+
(CUSTOM_MODEL_ID, "Other", "Enter a custom OpenAI model ID"),
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
LEVEL_PLACEHOLDERS: dict[str, list[str]] = {
|
|
134
|
+
"SESSION": ["context", "available_tools"],
|
|
135
|
+
"TRACE": ["context", "assistant_turn"],
|
|
136
|
+
"TOOL_CALL": [
|
|
137
|
+
"available_tools",
|
|
138
|
+
"context",
|
|
139
|
+
"tool_turn",
|
|
140
|
+
"available_skills",
|
|
141
|
+
"invoked_skill",
|
|
142
|
+
"skill_content",
|
|
143
|
+
"user_message",
|
|
144
|
+
],
|
|
145
|
+
}
|
|
146
|
+
REFERENCE_INPUT_PLACEHOLDERS: dict[str, list[str]] = {
|
|
147
|
+
"SESSION": ["assertions", "expected_tool_trajectory", "actual_tool_trajectory"],
|
|
148
|
+
"TRACE": ["expected_response"],
|
|
149
|
+
"TOOL_CALL": [],
|
|
150
|
+
}
|
|
151
|
+
PLACEHOLDER_DESCRIPTIONS: dict[str, str] = {
|
|
152
|
+
"context": "full conversation history (user + assistant messages)",
|
|
153
|
+
"assistant_turn": "the specific assistant response being evaluated",
|
|
154
|
+
"available_tools": "list of tools the agent can call",
|
|
155
|
+
"tool_turn": "the specific tool call and its result",
|
|
156
|
+
"assertions": "caller-provided assertions the agent should satisfy",
|
|
157
|
+
"expected_tool_trajectory": "caller-provided expected sequence of tool calls",
|
|
158
|
+
"actual_tool_trajectory": "actual sequence of tool calls from the session",
|
|
159
|
+
"expected_response": "caller-provided expected agent response",
|
|
160
|
+
"available_skills": "skills offered to the agent (name + description)",
|
|
161
|
+
"invoked_skill": "the skill the agent selected for this span",
|
|
162
|
+
"skill_content": "the selected skill's SKILL.md instructions",
|
|
163
|
+
"user_message": "the user request in the turn that triggered the skill invocation",
|
|
164
|
+
}
|
|
165
|
+
DEFAULT_INSTRUCTIONS: dict[str, str] = {
|
|
166
|
+
"SESSION": "Evaluate the agent session. Context: {context}. Available tools: {available_tools}. The agent must "
|
|
167
|
+
"satisfy: {assertions}. Expected trajectory: {expected_tool_trajectory}. Actual trajectory: "
|
|
168
|
+
"{actual_tool_trajectory}. Rate the overall quality.",
|
|
169
|
+
"TRACE": "Evaluate the agent trace. Context: {context}. Assistant turn: {assistant_turn}. Expected response: "
|
|
170
|
+
"{expected_response}. Rate the quality of this response.",
|
|
171
|
+
"TOOL_CALL": "Evaluate the tool call. Context: {context}. Tool turn: {tool_turn}. Rate the quality of this tool "
|
|
172
|
+
"usage.",
|
|
173
|
+
}
|
|
174
|
+
CUSTOM_RATING_SCALE_ID = "__custom__"
|
|
175
|
+
RATING_SCALE_TYPE_OPTIONS = (
|
|
176
|
+
("numerical", "Numerical", "Scored values (e.g. 1–5)"),
|
|
177
|
+
("categorical", "Categorical", "Named labels (e.g. Pass/Fail)"),
|
|
178
|
+
)
|
|
179
|
+
RATING_SCALE_PRESETS: list[dict[str, Any]] = [
|
|
180
|
+
{
|
|
181
|
+
"id": "1-5-quality",
|
|
182
|
+
"title": "1–5 Quality",
|
|
183
|
+
"description": "Numerical · Poor(1), Fair(2), Good(3), Very Good(4), Excellent(5)",
|
|
184
|
+
"ratingScale": {
|
|
185
|
+
"numerical": [
|
|
186
|
+
{"value": 1, "label": "Poor", "definition": "Fails to meet expectations"},
|
|
187
|
+
{"value": 2, "label": "Fair", "definition": "Partially meets expectations"},
|
|
188
|
+
{"value": 3, "label": "Good", "definition": "Meets expectations"},
|
|
189
|
+
{"value": 4, "label": "Very Good", "definition": "Exceeds expectations"},
|
|
190
|
+
{"value": 5, "label": "Excellent", "definition": "Far exceeds expectations"},
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"id": "1-3-simple",
|
|
196
|
+
"title": "1–3 Simple",
|
|
197
|
+
"description": "Numerical · Low(1), Medium(2), High(3)",
|
|
198
|
+
"ratingScale": {
|
|
199
|
+
"numerical": [
|
|
200
|
+
{"value": 1, "label": "Low", "definition": "Below acceptable quality"},
|
|
201
|
+
{"value": 2, "label": "Medium", "definition": "Acceptable quality"},
|
|
202
|
+
{"value": 3, "label": "High", "definition": "Above acceptable quality"},
|
|
203
|
+
]
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"id": "pass-fail",
|
|
208
|
+
"title": "Pass / Fail",
|
|
209
|
+
"description": "Categorical · binary pass or fail assessment",
|
|
210
|
+
"ratingScale": {
|
|
211
|
+
"categorical": [
|
|
212
|
+
{"label": "Pass", "definition": "Meets the evaluation criteria"},
|
|
213
|
+
{"label": "Fail", "definition": "Does not meet the evaluation criteria"},
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
"id": "good-neutral-bad",
|
|
219
|
+
"title": "Good / Neutral / Bad",
|
|
220
|
+
"description": "Categorical · three-tier quality assessment",
|
|
221
|
+
"ratingScale": {
|
|
222
|
+
"categorical": [
|
|
223
|
+
{"label": "Good", "definition": "Positive outcome, meets or exceeds criteria"},
|
|
224
|
+
{"label": "Neutral", "definition": "Acceptable but unremarkable outcome"},
|
|
225
|
+
{"label": "Bad", "definition": "Negative outcome, fails to meet criteria"},
|
|
226
|
+
]
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
]
|
|
230
|
+
PRESET_IDS = [p["id"] for p in RATING_SCALE_PRESETS]
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def validate_instruction_placeholders(instructions: str, level: str) -> str | None:
|
|
234
|
+
"""Error message unless the instructions contain a level placeholder."""
|
|
235
|
+
placeholders = LEVEL_PLACEHOLDERS[level]
|
|
236
|
+
if any(f"{{{p}}}" in instructions for p in placeholders):
|
|
237
|
+
return None
|
|
238
|
+
return f"Instructions must contain at least one placeholder: {', '.join(f'{{{p}}}' for p in placeholders)}"
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _js_number(raw: str) -> float | int | None:
|
|
242
|
+
"""``Number(raw)``; None for NaN."""
|
|
243
|
+
text = raw.strip()
|
|
244
|
+
if text == "":
|
|
245
|
+
return 0
|
|
246
|
+
try:
|
|
247
|
+
value = float(int(text, 0)) if re.fullmatch(r"0[xXoObB][0-9a-fA-F]+", text) else float(text)
|
|
248
|
+
except ValueError:
|
|
249
|
+
return None
|
|
250
|
+
if math.isnan(value):
|
|
251
|
+
return None
|
|
252
|
+
return int(value) if value.is_integer() else value
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def parse_custom_rating_scale(text: str, scale_type: str) -> tuple[bool, Any]:
|
|
256
|
+
"""(True, ratingScale) or (False, error) from "1:Poor:Def, 5:Great:Def" / "Pass:Def, Fail:Def"."""
|
|
257
|
+
entries = [e.strip() for e in text.split(",") if e.strip()]
|
|
258
|
+
if len(entries) < 2:
|
|
259
|
+
return False, "At least 2 entries required (comma-separated)"
|
|
260
|
+
if scale_type == "numerical":
|
|
261
|
+
numerical = []
|
|
262
|
+
for entry in entries:
|
|
263
|
+
first = entry.find(":")
|
|
264
|
+
second = entry.find(":", first + 1) if first >= 0 else -1
|
|
265
|
+
if first < 0 or second < 0:
|
|
266
|
+
return False, f'Invalid entry "{entry}". Format: value:label:definition'
|
|
267
|
+
raw = entry[:first].strip()
|
|
268
|
+
value = _js_number(raw)
|
|
269
|
+
if value is None:
|
|
270
|
+
return False, f'"{raw}" is not a valid number in "{entry}"'
|
|
271
|
+
numerical.append(
|
|
272
|
+
{"value": value, "label": entry[first + 1 : second].strip(), "definition": entry[second + 1 :].strip()}
|
|
273
|
+
)
|
|
274
|
+
return True, {"numerical": numerical}
|
|
275
|
+
categorical = []
|
|
276
|
+
for entry in entries:
|
|
277
|
+
first = entry.find(":")
|
|
278
|
+
if first < 0:
|
|
279
|
+
return False, f'Invalid entry "{entry}". Format: label:definition'
|
|
280
|
+
categorical.append({"label": entry[:first].strip(), "definition": entry[first + 1 :].strip()})
|
|
281
|
+
return True, {"categorical": categorical}
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def json_to_python_value(value: Any) -> str:
|
|
285
|
+
if value is None:
|
|
286
|
+
return "None"
|
|
287
|
+
if value is True:
|
|
288
|
+
return "True"
|
|
289
|
+
if value is False:
|
|
290
|
+
return "False"
|
|
291
|
+
if isinstance(value, (int, float)):
|
|
292
|
+
return str(int(value)) if isinstance(value, float) and value.is_integer() else str(value)
|
|
293
|
+
if isinstance(value, str):
|
|
294
|
+
return json.dumps(value, ensure_ascii=False)
|
|
295
|
+
if isinstance(value, list):
|
|
296
|
+
return f"[{', '.join(json_to_python_value(v) for v in value)}]"
|
|
297
|
+
if isinstance(value, dict):
|
|
298
|
+
return (
|
|
299
|
+
"{"
|
|
300
|
+
+ ", ".join(f"{json.dumps(k, ensure_ascii=False)}: {json_to_python_value(v)}" for k, v in value.items())
|
|
301
|
+
+ "}"
|
|
302
|
+
)
|
|
303
|
+
return str(value)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def json_to_kwargs(text: str) -> str:
|
|
307
|
+
obj = json.loads(text)
|
|
308
|
+
if not isinstance(obj, dict):
|
|
309
|
+
raise TypeError("Expected a JSON object of keyword arguments")
|
|
310
|
+
parts = []
|
|
311
|
+
for key, value in obj.items():
|
|
312
|
+
if not _KWARG_NAME.match(key):
|
|
313
|
+
raise Exception(f'Invalid Python kwarg name "{key}"')
|
|
314
|
+
parts.append(f"{key}={json_to_python_value(value)}")
|
|
315
|
+
return ", ".join(parts)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def get_warnings_for_metric(library_config: dict[str, Any], metric_class: str) -> list[str]:
|
|
319
|
+
return [f"⚠️ {metric_class} {w['message']}" for w in library_config["warnings"] if metric_class in w["metrics"]]
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _parse_schema(schema: Any, value: Any) -> tuple[bool, Any]:
|
|
323
|
+
try:
|
|
324
|
+
return True, TypeAdapter(schema).validate_python(value)
|
|
325
|
+
except PydanticValidationError as exc:
|
|
326
|
+
errors = exc.errors()
|
|
327
|
+
return False, errors[0]["msg"] if errors else str(exc)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
@dataclass
|
|
331
|
+
class ThirdPartyLibraryOptions:
|
|
332
|
+
library: str
|
|
333
|
+
metric_class: str
|
|
334
|
+
metric_params: str | None = None
|
|
335
|
+
model_provider: str | None = None
|
|
336
|
+
model: str | None = None
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
@dataclass
|
|
340
|
+
class AddEvaluatorOptions:
|
|
341
|
+
name: str
|
|
342
|
+
level: str
|
|
343
|
+
config: dict[str, Any]
|
|
344
|
+
description: str | None = None
|
|
345
|
+
kms_key_arn: str | None = None
|
|
346
|
+
third_party: ThirdPartyLibraryOptions | None = None
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def build_code_based_config(name: str, lambda_arn: str | None = None, timeout: str | None = None) -> dict:
|
|
350
|
+
if lambda_arn:
|
|
351
|
+
return {"codeBased": {"external": {"lambdaArn": lambda_arn}}}
|
|
352
|
+
return {
|
|
353
|
+
"codeBased": {
|
|
354
|
+
"managed": {
|
|
355
|
+
"codeLocation": f"app/{name}/",
|
|
356
|
+
"entrypoint": DEFAULT_CODE_ENTRYPOINT,
|
|
357
|
+
"timeoutSeconds": parse_int(timeout) if timeout else DEFAULT_CODE_TIMEOUT,
|
|
358
|
+
"additionalPolicies": ["execution-role-policy.json"],
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
def build_third_party_config(name: str, library_config: dict[str, Any], timeout: str | None = None) -> dict:
|
|
365
|
+
return {
|
|
366
|
+
"codeBased": {
|
|
367
|
+
"managed": {
|
|
368
|
+
"codeLocation": f"app/{name}/",
|
|
369
|
+
"entrypoint": DEFAULT_CODE_ENTRYPOINT,
|
|
370
|
+
"timeoutSeconds": parse_int(timeout) if timeout else library_config["defaultTimeoutSeconds"],
|
|
371
|
+
"additionalPolicies": ["execution-role-policy.json"],
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
class _Fail(Exception):
|
|
378
|
+
pass
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
class EvaluatorPrimitive(BasePrimitive):
|
|
382
|
+
kind = "evaluator"
|
|
383
|
+
label = "Evaluator"
|
|
384
|
+
article = "an"
|
|
385
|
+
|
|
386
|
+
def _project(self) -> dict[str, Any]:
|
|
387
|
+
return to_jsonable(self.read_project_spec())
|
|
388
|
+
|
|
389
|
+
def _project_root(self) -> str:
|
|
390
|
+
return os.path.dirname(find_config_root() or "")
|
|
391
|
+
|
|
392
|
+
def add(self, options: AddEvaluatorOptions) -> Ok | Err:
|
|
393
|
+
try:
|
|
394
|
+
evaluator: dict[str, Any] = {"name": options.name, "level": options.level}
|
|
395
|
+
if options.description:
|
|
396
|
+
evaluator["description"] = options.description
|
|
397
|
+
evaluator["config"] = options.config
|
|
398
|
+
if options.kms_key_arn:
|
|
399
|
+
evaluator["kmsKeyArn"] = options.kms_key_arn
|
|
400
|
+
|
|
401
|
+
def mutate(project: Any) -> Any:
|
|
402
|
+
data = to_jsonable(project)
|
|
403
|
+
self.check_duplicate([RemovableResource(e["name"]) for e in data["evaluators"]], options.name)
|
|
404
|
+
data["evaluators"].append(evaluator)
|
|
405
|
+
return data
|
|
406
|
+
|
|
407
|
+
self.update_project_spec(mutate)
|
|
408
|
+
|
|
409
|
+
managed = (options.config.get("codeBased") or {}).get("managed")
|
|
410
|
+
if managed:
|
|
411
|
+
target_dir = os.path.join(self._project_root(), managed["codeLocation"])
|
|
412
|
+
if options.third_party:
|
|
413
|
+
tp = options.third_party
|
|
414
|
+
data: dict[str, Any] = {
|
|
415
|
+
"Name": options.name,
|
|
416
|
+
"EvaluatorClass": tp.metric_class,
|
|
417
|
+
"EvaluatorParams": tp.metric_params or "",
|
|
418
|
+
}
|
|
419
|
+
if tp.model_provider == "bedrock":
|
|
420
|
+
data["ModelProviderBedrock"] = True
|
|
421
|
+
if tp.model:
|
|
422
|
+
data["Model"] = tp.model
|
|
423
|
+
render_third_party_evaluator_template(
|
|
424
|
+
THIRD_PARTY_EVALUATOR_LIBRARIES[tp.library]["templateDir"], data, target_dir
|
|
425
|
+
)
|
|
426
|
+
else:
|
|
427
|
+
render_code_based_evaluator_template(options.name, target_dir)
|
|
428
|
+
return Ok({"evaluatorName": options.name, "codePath": managed["codeLocation"]})
|
|
429
|
+
return Ok({"evaluatorName": options.name})
|
|
430
|
+
except Exception as exc: # noqa: BLE001
|
|
431
|
+
return Err(to_error(exc))
|
|
432
|
+
|
|
433
|
+
def remove(self, name: str) -> Ok | Err:
|
|
434
|
+
try:
|
|
435
|
+
project = self._project()
|
|
436
|
+
index = next((i for i, e in enumerate(project["evaluators"]) if e["name"] == name), -1)
|
|
437
|
+
if index == -1:
|
|
438
|
+
return Err(ResourceNotFoundError(f'Evaluator "{name}" not found.'))
|
|
439
|
+
refs = [c["name"] for c in project["onlineEvalConfigs"] if name in (c.get("evaluators") or [])]
|
|
440
|
+
if refs:
|
|
441
|
+
return Err(
|
|
442
|
+
ConflictError(
|
|
443
|
+
f'Evaluator "{name}" is referenced by online eval config(s): {", ".join(refs)}. '
|
|
444
|
+
"Remove those references first."
|
|
445
|
+
)
|
|
446
|
+
)
|
|
447
|
+
managed = ((project["evaluators"][index].get("config") or {}).get("codeBased") or {}).get("managed")
|
|
448
|
+
if managed:
|
|
449
|
+
code_dir = os.path.join(self._project_root(), managed["codeLocation"])
|
|
450
|
+
if os.path.exists(code_dir):
|
|
451
|
+
shutil.rmtree(code_dir, ignore_errors=True)
|
|
452
|
+
project["evaluators"].pop(index)
|
|
453
|
+
self.write_project_spec(project)
|
|
454
|
+
return Ok(None)
|
|
455
|
+
except Exception as exc: # noqa: BLE001
|
|
456
|
+
return Err(to_error(exc))
|
|
457
|
+
|
|
458
|
+
def preview_remove(self, name: str) -> RemovalPreview:
|
|
459
|
+
project = self._project()
|
|
460
|
+
evaluator = next((e for e in project["evaluators"] if e["name"] == name), None)
|
|
461
|
+
if evaluator is None:
|
|
462
|
+
raise Exception(f'Evaluator "{name}" not found.')
|
|
463
|
+
summary = [f"Removing evaluator: {name}"]
|
|
464
|
+
directories: list[str] = []
|
|
465
|
+
refs = [c["name"] for c in project["onlineEvalConfigs"] if name in (c.get("evaluators") or [])]
|
|
466
|
+
if refs:
|
|
467
|
+
summary.append(
|
|
468
|
+
f"Blocked: Referenced by online eval config(s): {', '.join(refs)}. Remove those references first."
|
|
469
|
+
)
|
|
470
|
+
managed = ((evaluator.get("config") or {}).get("codeBased") or {}).get("managed")
|
|
471
|
+
if managed:
|
|
472
|
+
location = managed["codeLocation"]
|
|
473
|
+
if os.path.exists(os.path.join(self._project_root(), location)):
|
|
474
|
+
directories.append(location)
|
|
475
|
+
summary.append(f"Will delete directory: {location}")
|
|
476
|
+
after = {**project, "evaluators": [e for e in project["evaluators"] if e["name"] != name]}
|
|
477
|
+
return RemovalPreview(summary, directories, [SchemaChange("agentcore/agentcore.json", project, after)])
|
|
478
|
+
|
|
479
|
+
def get_removable(self) -> list[RemovableResource]:
|
|
480
|
+
try:
|
|
481
|
+
return [RemovableResource(e["name"]) for e in self._project()["evaluators"]]
|
|
482
|
+
except Exception: # noqa: BLE001
|
|
483
|
+
return []
|
|
484
|
+
|
|
485
|
+
def get_all_names(self) -> list[str]:
|
|
486
|
+
return [r.name for r in self.get_removable()]
|
|
487
|
+
|
|
488
|
+
# --- CLI ----------------------------------------------------------------------------
|
|
489
|
+
|
|
490
|
+
def register_commands(self, add_app: typer.Typer, remove_app: typer.Typer) -> None:
|
|
491
|
+
@add_app.command("evaluator", help="Add a custom evaluator to the project")
|
|
492
|
+
def add_evaluator(
|
|
493
|
+
name: str | None = typer.Option(None, "--name", help="Evaluator name"),
|
|
494
|
+
level: str | None = typer.Option(None, "--level", help="Evaluation level: SESSION, TRACE, TOOL_CALL"),
|
|
495
|
+
type_: str | None = typer.Option(
|
|
496
|
+
None, "--type", help="Evaluator type: llm-as-a-judge (default) or code-based"
|
|
497
|
+
),
|
|
498
|
+
model: str | None = typer.Option(
|
|
499
|
+
None, "--model", help="[LLM] Bedrock inference profile ID or OpenResponses model ID for LLM-as-a-Judge"
|
|
500
|
+
),
|
|
501
|
+
model_provider: str | None = typer.Option(
|
|
502
|
+
None, "--model-provider", help="[LLM] Model provider: Bedrock (default) or OpenResponses"
|
|
503
|
+
),
|
|
504
|
+
instructions: str | None = typer.Option(
|
|
505
|
+
None,
|
|
506
|
+
"--instructions",
|
|
507
|
+
help="[LLM] Evaluation prompt instructions (must include level-appropriate placeholders, e.g. {context})",
|
|
508
|
+
),
|
|
509
|
+
rating_scale: str | None = typer.Option(
|
|
510
|
+
None,
|
|
511
|
+
"--rating-scale",
|
|
512
|
+
help=f"[LLM] Rating scale preset: {', '.join(PRESET_IDS)} (default: 1-5-quality)",
|
|
513
|
+
),
|
|
514
|
+
lambda_arn: str | None = typer.Option(
|
|
515
|
+
None, "--lambda-arn", help="[Code-based] Existing Lambda function ARN (external)"
|
|
516
|
+
),
|
|
517
|
+
timeout: str | None = typer.Option(
|
|
518
|
+
None, "--timeout", help="[Code-based] Lambda timeout in seconds, 1-300 (default: 60)"
|
|
519
|
+
),
|
|
520
|
+
template_json: str | None = typer.Option(
|
|
521
|
+
None,
|
|
522
|
+
"--3p-template-json",
|
|
523
|
+
help='[Code-based] Inline JSON with 3P library config: {"library", "metric", "modelProvider", '
|
|
524
|
+
'"model", "params"}',
|
|
525
|
+
),
|
|
526
|
+
template_json_file: str | None = typer.Option(
|
|
527
|
+
None,
|
|
528
|
+
"--3p-template-json-file",
|
|
529
|
+
help="[Code-based] Path to JSON file with 3P library config (same format as --3p-template-json)",
|
|
530
|
+
),
|
|
531
|
+
config: str | None = typer.Option(
|
|
532
|
+
None,
|
|
533
|
+
"--config",
|
|
534
|
+
help="Path to evaluator config JSON file (overrides --model, --instructions, --rating-scale) "
|
|
535
|
+
"[non-interactive]",
|
|
536
|
+
),
|
|
537
|
+
kms_key_arn: str | None = typer.Option(
|
|
538
|
+
None, "--kms-key-arn", help="KMS key ARN for evaluator encryption (optional)"
|
|
539
|
+
),
|
|
540
|
+
as_json: bool = typer.Option(False, "--json", help="Output as JSON [non-interactive]"),
|
|
541
|
+
) -> None:
|
|
542
|
+
if not find_config_root():
|
|
543
|
+
typer.echo("No agentcore project found. Run `agentcore create` first.", err=True)
|
|
544
|
+
raise typer.Exit(1)
|
|
545
|
+
if not (name or as_json):
|
|
546
|
+
try:
|
|
547
|
+
interactive.require_tty()
|
|
548
|
+
self.add_interactive()
|
|
549
|
+
except typer.Exit:
|
|
550
|
+
raise
|
|
551
|
+
except Exception as exc: # noqa: BLE001
|
|
552
|
+
typer.echo(get_error_message(exc), err=True)
|
|
553
|
+
raise typer.Exit(1) from None
|
|
554
|
+
raise typer.Exit(0)
|
|
555
|
+
|
|
556
|
+
run_cli_command(
|
|
557
|
+
as_json,
|
|
558
|
+
lambda: self._add_from_flags(
|
|
559
|
+
name=name,
|
|
560
|
+
level=level,
|
|
561
|
+
eval_type=type_,
|
|
562
|
+
model=model,
|
|
563
|
+
model_provider=model_provider,
|
|
564
|
+
instructions=instructions,
|
|
565
|
+
rating_scale=rating_scale,
|
|
566
|
+
lambda_arn=lambda_arn,
|
|
567
|
+
timeout=timeout,
|
|
568
|
+
template_json=template_json,
|
|
569
|
+
template_json_file=template_json_file,
|
|
570
|
+
config=config,
|
|
571
|
+
kms_key_arn=kms_key_arn,
|
|
572
|
+
as_json=as_json,
|
|
573
|
+
),
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
self.register_remove_subcommand(remove_app)
|
|
577
|
+
|
|
578
|
+
def _add_from_flags(self, **o: Any) -> None:
|
|
579
|
+
def fail(message: str) -> None:
|
|
580
|
+
raise Exception(message)
|
|
581
|
+
|
|
582
|
+
name, level = o["name"], o["level"]
|
|
583
|
+
if not name or not level:
|
|
584
|
+
fail("--name and --level are required in non-interactive mode")
|
|
585
|
+
if level not in EVALUATION_LEVELS:
|
|
586
|
+
fail(f'Invalid --level "{level}". Must be one of: SESSION, TRACE, TOOL_CALL')
|
|
587
|
+
if o["template_json"] and o["template_json_file"]:
|
|
588
|
+
fail("--3p-template-json and --3p-template-json-file cannot be used together")
|
|
589
|
+
template_text = None
|
|
590
|
+
if o["template_json"]:
|
|
591
|
+
template_text = o["template_json"]
|
|
592
|
+
elif o["template_json_file"]:
|
|
593
|
+
if not os.path.exists(o["template_json_file"]):
|
|
594
|
+
fail(f"--3p-template-json-file not found: {o['template_json_file']}")
|
|
595
|
+
with open(o["template_json_file"], encoding="utf-8") as fh:
|
|
596
|
+
template_text = fh.read()
|
|
597
|
+
|
|
598
|
+
library = metric = tp_provider = tp_model = tp_params = None
|
|
599
|
+
if template_text:
|
|
600
|
+
try:
|
|
601
|
+
template = json.loads(template_text)
|
|
602
|
+
except ValueError:
|
|
603
|
+
raise Exception("--3p-template-json must be valid JSON") from None
|
|
604
|
+
if not isinstance(template, dict):
|
|
605
|
+
template = {}
|
|
606
|
+
if not template.get("library") or not isinstance(template.get("library"), str):
|
|
607
|
+
fail('--3p-template-json must include "library" (e.g. "deepeval" or "autoevals")')
|
|
608
|
+
if not template.get("metric") or not isinstance(template.get("metric"), str):
|
|
609
|
+
fail('--3p-template-json must include "metric" (e.g. "AnswerRelevancyMetric")')
|
|
610
|
+
library = str(template["library"])
|
|
611
|
+
if library not in THIRD_PARTY_EVALUATOR_LIBRARIES:
|
|
612
|
+
fail(f'Invalid library "{library}". Supported: {", ".join(SUPPORTED_LIBRARIES)}')
|
|
613
|
+
metric = template["metric"]
|
|
614
|
+
if template.get("modelProvider"):
|
|
615
|
+
raw_provider = str(template["modelProvider"])
|
|
616
|
+
if raw_provider.lower() not in MODEL_PROVIDERS:
|
|
617
|
+
fail(f'Invalid modelProvider "{raw_provider}". Supported: {", ".join(MODEL_PROVIDERS)}')
|
|
618
|
+
tp_provider = raw_provider.lower()
|
|
619
|
+
if template.get("model"):
|
|
620
|
+
tp_model = template["model"]
|
|
621
|
+
if template.get("params") and isinstance(template["params"], (dict, list)):
|
|
622
|
+
try:
|
|
623
|
+
params = template["params"]
|
|
624
|
+
items = params.items() if isinstance(params, dict) else enumerate(params)
|
|
625
|
+
parts = []
|
|
626
|
+
for k, v in items:
|
|
627
|
+
if not _KWARG_NAME.match(str(k)):
|
|
628
|
+
raise Exception(f'Invalid Python kwarg name "{k}"')
|
|
629
|
+
parts.append(f"{k}={json_to_python_value(v)}")
|
|
630
|
+
tp_params = ", ".join(parts)
|
|
631
|
+
except Exception as exc: # noqa: BLE001
|
|
632
|
+
fail(f"Invalid params in --3p-template-json: {get_error_message(exc)}")
|
|
633
|
+
if not tp_provider and tp_model:
|
|
634
|
+
tp_provider = "bedrock"
|
|
635
|
+
if tp_provider == "bedrock" and not tp_model:
|
|
636
|
+
fail(
|
|
637
|
+
'--3p-template-json requires "model" when modelProvider is bedrock. '
|
|
638
|
+
"Pass a Bedrock inference profile ID (e.g. us.anthropic.claude-sonnet-4-20250514-v1:0)"
|
|
639
|
+
)
|
|
640
|
+
if tp_provider == "openai":
|
|
641
|
+
typer.echo(
|
|
642
|
+
"\n ⚠️ OpenAI model provider selected. You must set OPENAI_API_KEY as a Lambda "
|
|
643
|
+
"environment variable after deployment.\n",
|
|
644
|
+
err=True,
|
|
645
|
+
)
|
|
646
|
+
|
|
647
|
+
timeout = o["timeout"]
|
|
648
|
+
if timeout:
|
|
649
|
+
value = parse_int(timeout)
|
|
650
|
+
if value is None or value < 1 or value > 300:
|
|
651
|
+
fail("--timeout must be an integer between 1 and 300")
|
|
652
|
+
|
|
653
|
+
eval_type = o["eval_type"] or ("code-based" if library else "llm-as-a-judge")
|
|
654
|
+
if eval_type not in ("llm-as-a-judge", "code-based"):
|
|
655
|
+
fail(f'Invalid --type "{eval_type}". Must be one of: llm-as-a-judge, code-based')
|
|
656
|
+
if eval_type != "code-based":
|
|
657
|
+
if o["lambda_arn"]:
|
|
658
|
+
fail("--lambda-arn requires --type code-based")
|
|
659
|
+
if timeout:
|
|
660
|
+
fail("--timeout requires --type code-based")
|
|
661
|
+
if library:
|
|
662
|
+
fail("--3p-template-json requires --type code-based")
|
|
663
|
+
if eval_type == "code-based":
|
|
664
|
+
if o["model"]:
|
|
665
|
+
fail("--model cannot be used with --type code-based")
|
|
666
|
+
if o["model_provider"]:
|
|
667
|
+
fail("--model-provider cannot be used with --type code-based")
|
|
668
|
+
if o["instructions"]:
|
|
669
|
+
fail("--instructions cannot be used with --type code-based")
|
|
670
|
+
if o["rating_scale"]:
|
|
671
|
+
fail("--rating-scale cannot be used with --type code-based")
|
|
672
|
+
if o["config"] and o["model_provider"]:
|
|
673
|
+
fail(
|
|
674
|
+
"--model-provider cannot be used with --config; set config.llmAsAJudge.modelProvider in the config file"
|
|
675
|
+
)
|
|
676
|
+
|
|
677
|
+
third_party = None
|
|
678
|
+
if library:
|
|
679
|
+
config = build_third_party_config(name, THIRD_PARTY_EVALUATOR_LIBRARIES[library], timeout)
|
|
680
|
+
third_party = ThirdPartyLibraryOptions(library, metric, tp_params, tp_provider, tp_model) # type: ignore[arg-type]
|
|
681
|
+
elif o["config"]:
|
|
682
|
+
with open(o["config"], encoding="utf-8") as fh:
|
|
683
|
+
config = json.load(fh)
|
|
684
|
+
elif eval_type == "code-based":
|
|
685
|
+
config = build_code_based_config(name, o["lambda_arn"], timeout)
|
|
686
|
+
else:
|
|
687
|
+
if not o["model"]:
|
|
688
|
+
fail("Either --config or --model is required for LLM-as-a-Judge evaluators")
|
|
689
|
+
ok, model_id = _parse_schema(EvaluatorModelId, o["model"])
|
|
690
|
+
if not ok:
|
|
691
|
+
fail(model_id or "Invalid --model")
|
|
692
|
+
provider = o["model_provider"] if o["model_provider"] is not None else "Bedrock"
|
|
693
|
+
if provider not in ("Bedrock", "OpenResponses"):
|
|
694
|
+
fail(f'Invalid --model-provider "{o["model_provider"]}". Must be one of: Bedrock, OpenResponses')
|
|
695
|
+
instructions = o["instructions"]
|
|
696
|
+
if not instructions:
|
|
697
|
+
placeholders = ", ".join(f"{{{p}}}" for p in LEVEL_PLACEHOLDERS[level])
|
|
698
|
+
fail(
|
|
699
|
+
"--instructions is required in non-interactive mode (or use --config). "
|
|
700
|
+
f"Must include at least one placeholder for {level}: {placeholders}"
|
|
701
|
+
)
|
|
702
|
+
problem = validate_instruction_placeholders(instructions, level)
|
|
703
|
+
if problem:
|
|
704
|
+
fail(problem)
|
|
705
|
+
scale_input = o["rating_scale"] if o["rating_scale"] is not None else "1-5-quality"
|
|
706
|
+
preset = next((p for p in RATING_SCALE_PRESETS if p["id"] == scale_input), None)
|
|
707
|
+
if preset:
|
|
708
|
+
scale = preset["ratingScale"]
|
|
709
|
+
else:
|
|
710
|
+
numerical = bool(re.match(r"^\d", scale_input.strip()))
|
|
711
|
+
ok, scale = parse_custom_rating_scale(scale_input, "numerical" if numerical else "categorical")
|
|
712
|
+
if not ok:
|
|
713
|
+
fail(
|
|
714
|
+
f'Invalid --rating-scale "{scale_input}". Use a preset ({", ".join(PRESET_IDS)}) '
|
|
715
|
+
'or custom format: "1:Label:Definition, 2:Label:Definition" (numerical) '
|
|
716
|
+
'or "Label:Definition, Label:Definition" (categorical)'
|
|
717
|
+
)
|
|
718
|
+
llm: dict[str, Any] = {}
|
|
719
|
+
if provider == "OpenResponses":
|
|
720
|
+
llm["modelProvider"] = provider
|
|
721
|
+
llm.update({"model": model_id, "instructions": instructions, "ratingScale": scale})
|
|
722
|
+
config = {"llmAsAJudge": llm}
|
|
723
|
+
|
|
724
|
+
if o["kms_key_arn"] and not is_valid_kms_key_arn(o["kms_key_arn"]):
|
|
725
|
+
fail(KMS_ARN_ERROR)
|
|
726
|
+
|
|
727
|
+
result = self.add(
|
|
728
|
+
AddEvaluatorOptions(
|
|
729
|
+
name=name, level=level, config=config, kms_key_arn=o["kms_key_arn"], third_party=third_party
|
|
730
|
+
)
|
|
731
|
+
)
|
|
732
|
+
if not result.success:
|
|
733
|
+
raise result.error
|
|
734
|
+
if o["as_json"]:
|
|
735
|
+
emit_json(serialize_result(result))
|
|
736
|
+
return
|
|
737
|
+
value = result.value
|
|
738
|
+
if value.get("codePath"):
|
|
739
|
+
typer.echo(f"Created evaluator '{value['evaluatorName']}'")
|
|
740
|
+
typer.echo(f" Code: {value['codePath']}lambda_function.py")
|
|
741
|
+
typer.echo(f" IAM: {value['codePath']}execution-role-policy.json")
|
|
742
|
+
typer.echo("\n Next: Edit lambda_function.py with your evaluation logic, then run `agentcore deploy`")
|
|
743
|
+
else:
|
|
744
|
+
typer.echo(f"Added evaluator '{value['evaluatorName']}'")
|
|
745
|
+
if third_party:
|
|
746
|
+
for warning in get_warnings_for_metric(
|
|
747
|
+
THIRD_PARTY_EVALUATOR_LIBRARIES[third_party.library], third_party.metric_class
|
|
748
|
+
):
|
|
749
|
+
typer.echo(f"\n {warning}", err=True)
|
|
750
|
+
if third_party.model_provider == "openai":
|
|
751
|
+
typer.echo(
|
|
752
|
+
"\n ⚠️ OpenAI model provider selected. You must set OPENAI_API_KEY as a Lambda "
|
|
753
|
+
"environment variable for the evaluator to call the LLM judge.",
|
|
754
|
+
err=True,
|
|
755
|
+
)
|
|
756
|
+
|
|
757
|
+
# --- interactive (tui/screens/evaluator/AddEvaluatorScreen) ---------------------------
|
|
758
|
+
|
|
759
|
+
def add_interactive(self) -> None:
|
|
760
|
+
existing = self.get_all_names()
|
|
761
|
+
choice = interactive.Choice
|
|
762
|
+
eval_type = interactive.select(
|
|
763
|
+
"What type of evaluator would you like to create?",
|
|
764
|
+
[choice(t, i, d) for i, t, d in EVALUATOR_TYPE_OPTIONS],
|
|
765
|
+
)
|
|
766
|
+
code_type = "managed"
|
|
767
|
+
if eval_type == "code-based":
|
|
768
|
+
code_type = interactive.select(
|
|
769
|
+
"How would you like to provide the Lambda?", [choice(t, i, d) for i, t, d in CODE_BASED_TYPE_OPTIONS]
|
|
770
|
+
)
|
|
771
|
+
|
|
772
|
+
def validate_name(value: str) -> str | None:
|
|
773
|
+
ok, msg = _parse_schema(EvaluatorName, value)
|
|
774
|
+
if not ok:
|
|
775
|
+
return msg
|
|
776
|
+
return "Evaluator name already exists" if value in existing else None
|
|
777
|
+
|
|
778
|
+
name = interactive.text(
|
|
779
|
+
"Evaluator name", default=generate_unique_name("MyEvaluator", existing), validate=validate_name
|
|
780
|
+
)
|
|
781
|
+
level = interactive.select(
|
|
782
|
+
"What level should this evaluator operate at?", [choice(t, i, d) for i, t, d in EVALUATION_LEVEL_OPTIONS]
|
|
783
|
+
)
|
|
784
|
+
rows: list[tuple[str, str]] = [("Type", eval_type), ("Name", name), ("Level", level)]
|
|
785
|
+
|
|
786
|
+
if eval_type == "llm-as-a-judge":
|
|
787
|
+
provider = interactive.select(
|
|
788
|
+
"Select model provider", [choice(t, i, d) for i, t, d in EVALUATOR_MODEL_PROVIDER_OPTIONS]
|
|
789
|
+
)
|
|
790
|
+
options = OPENAI_EVALUATOR_MODEL_OPTIONS if provider == "OpenResponses" else BEDROCK_EVALUATOR_MODEL_OPTIONS
|
|
791
|
+
model = interactive.select("Select model", [choice(t, i, d) for i, t, d in options])
|
|
792
|
+
if model == CUSTOM_MODEL_ID:
|
|
793
|
+
if provider == "OpenResponses":
|
|
794
|
+
model = interactive.text(
|
|
795
|
+
"OpenResponses model ID",
|
|
796
|
+
validate=lambda v: (
|
|
797
|
+
None
|
|
798
|
+
if _parse_schema(EvaluatorModelId, v)[0]
|
|
799
|
+
else "A valid OpenResponses model ID is required"
|
|
800
|
+
),
|
|
801
|
+
)
|
|
802
|
+
else:
|
|
803
|
+
model = interactive.text(
|
|
804
|
+
"Bedrock model ID",
|
|
805
|
+
validate=lambda v: (
|
|
806
|
+
None
|
|
807
|
+
if is_valid_bedrock_model_id(v)
|
|
808
|
+
else "Must be a valid Bedrock model ID (e.g. us.anthropic.claude-sonnet-4-5-20250929-v1:0) "
|
|
809
|
+
"or model ARN"
|
|
810
|
+
),
|
|
811
|
+
)
|
|
812
|
+
typer.echo("Evaluation instructions")
|
|
813
|
+
typer.echo("Available placeholders:")
|
|
814
|
+
for p in LEVEL_PLACEHOLDERS[level]:
|
|
815
|
+
typer.echo(f" {{{p}}} — {PLACEHOLDER_DESCRIPTIONS.get(p, p)}")
|
|
816
|
+
if REFERENCE_INPUT_PLACEHOLDERS[level]:
|
|
817
|
+
typer.echo("Reference inputs — provided by caller at eval time, may be empty:")
|
|
818
|
+
for p in REFERENCE_INPUT_PLACEHOLDERS[level]:
|
|
819
|
+
typer.echo(f" {{{p}}} — {PLACEHOLDER_DESCRIPTIONS.get(p, p)}")
|
|
820
|
+
instructions = interactive.text(
|
|
821
|
+
"Instructions",
|
|
822
|
+
default=DEFAULT_INSTRUCTIONS[level],
|
|
823
|
+
validate=lambda v: validate_instruction_placeholders(v, level),
|
|
824
|
+
)
|
|
825
|
+
scale_id = interactive.select(
|
|
826
|
+
"Rating scale",
|
|
827
|
+
[choice(p["title"], p["id"], p["description"]) for p in RATING_SCALE_PRESETS]
|
|
828
|
+
+ [choice("Custom", CUSTOM_RATING_SCALE_ID, "Define your own rating scale")],
|
|
829
|
+
)
|
|
830
|
+
if scale_id == CUSTOM_RATING_SCALE_ID:
|
|
831
|
+
scale_type = interactive.select(
|
|
832
|
+
"Scale type", [choice(t, i, d) for i, t, d in RATING_SCALE_TYPE_OPTIONS]
|
|
833
|
+
)
|
|
834
|
+
typer.echo("Define rating scale entries")
|
|
835
|
+
typer.echo(
|
|
836
|
+
"Format: value:label:definition, ... (e.g. 1:Poor:Fails, 3:Good:Meets, 5:Excellent:Exceeds)"
|
|
837
|
+
if scale_type == "numerical"
|
|
838
|
+
else "Format: label:definition, ... (e.g. Pass:Meets criteria, Fail:Does not meet)"
|
|
839
|
+
)
|
|
840
|
+
scale_text = interactive.text(
|
|
841
|
+
"Entries",
|
|
842
|
+
validate=lambda v: (
|
|
843
|
+
None
|
|
844
|
+
if parse_custom_rating_scale(v, scale_type)[0]
|
|
845
|
+
else parse_custom_rating_scale(v, scale_type)[1]
|
|
846
|
+
),
|
|
847
|
+
)
|
|
848
|
+
scale = parse_custom_rating_scale(scale_text, scale_type)[1]
|
|
849
|
+
else:
|
|
850
|
+
scale = next(p["ratingScale"] for p in RATING_SCALE_PRESETS if p["id"] == scale_id)
|
|
851
|
+
llm: dict[str, Any] = {}
|
|
852
|
+
if provider == "OpenResponses":
|
|
853
|
+
llm["modelProvider"] = provider
|
|
854
|
+
llm.update({"model": model, "instructions": instructions, "ratingScale": scale})
|
|
855
|
+
config: dict[str, Any] = {"llmAsAJudge": llm}
|
|
856
|
+
rows += [("Provider", provider), ("Model", model), ("Prompt", instructions)]
|
|
857
|
+
elif code_type == "external":
|
|
858
|
+
arn = interactive.text(
|
|
859
|
+
"Lambda function ARN",
|
|
860
|
+
validate=lambda v: None if _LAMBDA_ARN.match(v) else "Must be a valid Lambda function ARN",
|
|
861
|
+
)
|
|
862
|
+
config = build_code_based_config(name, arn)
|
|
863
|
+
rows.append(("Lambda", arn))
|
|
864
|
+
else:
|
|
865
|
+
|
|
866
|
+
def validate_timeout(v: str) -> str | None:
|
|
867
|
+
num = parse_int(v)
|
|
868
|
+
if num is None:
|
|
869
|
+
return "Must be a number"
|
|
870
|
+
return None if 1 <= num <= 300 else "Must be between 1 and 300"
|
|
871
|
+
|
|
872
|
+
timeout = interactive.text(
|
|
873
|
+
"Lambda timeout in seconds (1-300)", default=str(DEFAULT_CODE_TIMEOUT), validate=validate_timeout
|
|
874
|
+
)
|
|
875
|
+
config = build_code_based_config(name, None, timeout)
|
|
876
|
+
rows.append(("Timeout", f"{parse_int(timeout)}s"))
|
|
877
|
+
|
|
878
|
+
kms = interactive.text(
|
|
879
|
+
"KMS key ARN for encryption (optional, press Enter to skip)",
|
|
880
|
+
validate=lambda v: (
|
|
881
|
+
None
|
|
882
|
+
if v == "" or is_valid_kms_key_arn(v)
|
|
883
|
+
else "Must be a valid KMS key ARN (e.g. arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012)"
|
|
884
|
+
),
|
|
885
|
+
)
|
|
886
|
+
if kms:
|
|
887
|
+
rows.append(("KMS Key", kms))
|
|
888
|
+
for label, value in rows:
|
|
889
|
+
typer.echo(f" {label}: {value}")
|
|
890
|
+
if not interactive.confirm("Add this evaluator?", default=True):
|
|
891
|
+
typer.echo("Cancelled.")
|
|
892
|
+
return
|
|
893
|
+
result = self.add(AddEvaluatorOptions(name=name, level=level, config=config, kms_key_arn=kms or None))
|
|
894
|
+
if not result.success:
|
|
895
|
+
typer.echo("Failed to add evaluator", err=True)
|
|
896
|
+
typer.echo(get_error_message(result.error), err=True)
|
|
897
|
+
raise typer.Exit(1)
|
|
898
|
+
typer.echo(f"Added evaluator: {name}")
|
|
899
|
+
code_path = result.value.get("codePath")
|
|
900
|
+
if code_path:
|
|
901
|
+
typer.echo(f'Created evaluator "{name}"')
|
|
902
|
+
typer.echo(f" Code: {code_path}lambda_function.py")
|
|
903
|
+
typer.echo(f" IAM: {code_path}execution-role-policy.json")
|
|
904
|
+
typer.echo("\n Next: Edit lambda_function.py with your evaluation logic, then run `agentcore deploy`")
|
|
905
|
+
else:
|
|
906
|
+
typer.echo("Evaluator added to project in `agentcore/agentcore.json`. Deploy with `agentcore deploy`.")
|
|
907
|
+
|
|
908
|
+
|
|
909
|
+
PRIMITIVE = EvaluatorPrimitive()
|