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,187 @@
|
|
|
1
|
+
"""Job Engine (port of operations/jobs/shared/engine.ts).
|
|
2
|
+
|
|
3
|
+
``create_job_engine(config_io)`` per call site. The engine owns persistence (start -> save) and
|
|
4
|
+
the refresh-on-read lifecycle; commands stay thin. Start options are dicts keyed by the upstream
|
|
5
|
+
(camelCase) option names; records are the camelCase dicts written to disk.
|
|
6
|
+
|
|
7
|
+
Handlers are modules exposing ``create(opts, config_io)``, ``refresh(record)``, ``archive(record)``
|
|
8
|
+
and, per type, ``stop``/``pause``/``resume``/``promote``/``debug``/``settle``. All return ``Ok``/``Err``
|
|
9
|
+
(``settle`` returns the record).
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from collections.abc import Callable
|
|
13
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
14
|
+
from functools import cmp_to_key
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from agentcore.aws import account
|
|
18
|
+
from agentcore.lib import ConfigIO, JobNotFoundError
|
|
19
|
+
from agentcore.lib.errors.types import to_error
|
|
20
|
+
from agentcore.lib.result import Err, Ok
|
|
21
|
+
from agentcore.operations.jobs.shared import storage
|
|
22
|
+
from agentcore.operations.jobs.shared.constants import JOB_CAPABILITIES, JOB_TYPE_LABELS, is_terminal
|
|
23
|
+
|
|
24
|
+
REFRESH_MAX_RETRIES = 3
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _handlers() -> dict[str, Any]:
|
|
28
|
+
from agentcore.operations.jobs.ab_test import handler as ab_test
|
|
29
|
+
from agentcore.operations.jobs.batch_evaluation import handler as batch_evaluation
|
|
30
|
+
from agentcore.operations.jobs.insights import handler as insights
|
|
31
|
+
from agentcore.operations.jobs.recommendation import handler as recommendation
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
"recommendation": recommendation,
|
|
35
|
+
"batch-evaluation": batch_evaluation,
|
|
36
|
+
"ab-test": ab_test,
|
|
37
|
+
"insights": insights,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _compare(a: dict[str, Any], b: dict[str, Any]) -> int:
|
|
42
|
+
"""Newest first by createdAt, ties by id ascending (string comparison, as upstream)."""
|
|
43
|
+
ac, bc = a.get("createdAt") or "", b.get("createdAt") or ""
|
|
44
|
+
if bc > ac:
|
|
45
|
+
return 1
|
|
46
|
+
if bc < ac:
|
|
47
|
+
return -1
|
|
48
|
+
return -1 if a.get("id", "") < b.get("id", "") else 1
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class JobEngine:
|
|
52
|
+
def __init__(self, config_io: ConfigIO | None = None, handlers: dict[str, Any] | None = None):
|
|
53
|
+
self._config_io = config_io
|
|
54
|
+
self._handlers = handlers
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def config_io(self) -> ConfigIO:
|
|
58
|
+
if self._config_io is None:
|
|
59
|
+
self._config_io = ConfigIO()
|
|
60
|
+
return self._config_io
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def handlers(self) -> dict[str, Any]:
|
|
64
|
+
if self._handlers is None:
|
|
65
|
+
self._handlers = _handlers()
|
|
66
|
+
return self._handlers
|
|
67
|
+
|
|
68
|
+
# --- lifecycle helpers ------------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
def _refresh_one(self, record: dict[str, Any]) -> dict[str, Any]:
|
|
71
|
+
if is_terminal(record):
|
|
72
|
+
return record
|
|
73
|
+
handler = self.handlers[record["type"]]
|
|
74
|
+
last_err: BaseException | None = None
|
|
75
|
+
for _ in range(REFRESH_MAX_RETRIES):
|
|
76
|
+
try:
|
|
77
|
+
result = handler.refresh(record)
|
|
78
|
+
except Exception as exc: # noqa: BLE001 - treated like a failed Result
|
|
79
|
+
result = Err(to_error(exc))
|
|
80
|
+
if result.success:
|
|
81
|
+
updated = dict(result.value)
|
|
82
|
+
updated.pop("error", None)
|
|
83
|
+
storage.save_record(updated)
|
|
84
|
+
return updated
|
|
85
|
+
last_err = result.error
|
|
86
|
+
failed = {**record, "error": str(last_err)}
|
|
87
|
+
storage.save_record(failed)
|
|
88
|
+
return failed
|
|
89
|
+
|
|
90
|
+
def _settle_one(self, record: dict[str, Any]) -> dict[str, Any]:
|
|
91
|
+
settle = getattr(self.handlers[record["type"]], "settle", None)
|
|
92
|
+
if settle is None:
|
|
93
|
+
return record
|
|
94
|
+
try:
|
|
95
|
+
settled = settle(record, self.config_io)
|
|
96
|
+
if settled is not record:
|
|
97
|
+
storage.save_record(settled)
|
|
98
|
+
return settled
|
|
99
|
+
except Exception: # noqa: BLE001 - settle failures leave the record unsynced (retried later)
|
|
100
|
+
return record
|
|
101
|
+
|
|
102
|
+
def _not_found(self, job_type: str, job_id: str) -> Err:
|
|
103
|
+
return Err(JobNotFoundError(f'{JOB_TYPE_LABELS[job_type]} "{job_id}" not found.'))
|
|
104
|
+
|
|
105
|
+
# --- public API -------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
def start(self, job_type: str, opts: dict[str, Any]) -> Ok | Err:
|
|
108
|
+
try:
|
|
109
|
+
account.validate_aws_credentials()
|
|
110
|
+
except Exception as exc: # noqa: BLE001
|
|
111
|
+
return Err(to_error(exc))
|
|
112
|
+
result = self.handlers[job_type].create(opts, self.config_io)
|
|
113
|
+
if result.success:
|
|
114
|
+
storage.save_record(result.value)
|
|
115
|
+
return result
|
|
116
|
+
|
|
117
|
+
def get(self, job_type: str, job_id: str) -> dict[str, Any] | None:
|
|
118
|
+
record = storage.load_record(job_type, job_id)
|
|
119
|
+
if record is None:
|
|
120
|
+
return None
|
|
121
|
+
return self._settle_one(self._refresh_one(record))
|
|
122
|
+
|
|
123
|
+
def list(self, *, type: str | None = None, limit: int | None = None, agent: str | None = None) -> list[dict]:
|
|
124
|
+
records = storage.list_records(type)
|
|
125
|
+
if len(records) > 1:
|
|
126
|
+
with ThreadPoolExecutor(max_workers=min(8, len(records))) as pool:
|
|
127
|
+
refreshed = list(pool.map(self._refresh_one, records))
|
|
128
|
+
else:
|
|
129
|
+
refreshed = [self._refresh_one(r) for r in records]
|
|
130
|
+
# Config-mutating settle steps run sequentially (no concurrent agentcore.json writes).
|
|
131
|
+
out = [self._settle_one(r) for r in refreshed]
|
|
132
|
+
if agent:
|
|
133
|
+
out = [r for r in out if r.get("agent") == agent]
|
|
134
|
+
out.sort(key=cmp_to_key(_compare))
|
|
135
|
+
if limit is not None:
|
|
136
|
+
out = out[:limit]
|
|
137
|
+
return out
|
|
138
|
+
|
|
139
|
+
def _with_record(self, job_type: str, job_id: str, fn: Callable[[dict[str, Any]], Ok | Err]) -> Ok | Err:
|
|
140
|
+
record = storage.load_record(job_type, job_id)
|
|
141
|
+
if record is None:
|
|
142
|
+
return self._not_found(job_type, job_id)
|
|
143
|
+
return fn(record)
|
|
144
|
+
|
|
145
|
+
def stop(self, job_type: str, job_id: str) -> Ok | Err:
|
|
146
|
+
def run(record: dict[str, Any]) -> Ok | Err:
|
|
147
|
+
result = self.handlers[job_type].stop(record)
|
|
148
|
+
if result.success:
|
|
149
|
+
storage.save_record({**record, "status": "STOPPING"})
|
|
150
|
+
return result
|
|
151
|
+
|
|
152
|
+
return self._with_record(job_type, job_id, run)
|
|
153
|
+
|
|
154
|
+
def _save_result(self, result: Ok | Err) -> Ok | Err:
|
|
155
|
+
if result.success:
|
|
156
|
+
storage.save_record(result.value)
|
|
157
|
+
return result
|
|
158
|
+
|
|
159
|
+
def pause(self, job_type: str, job_id: str) -> Ok | Err:
|
|
160
|
+
return self._with_record(job_type, job_id, lambda r: self._save_result(self.handlers[job_type].pause(r)))
|
|
161
|
+
|
|
162
|
+
def resume(self, job_type: str, job_id: str) -> Ok | Err:
|
|
163
|
+
return self._with_record(job_type, job_id, lambda r: self._save_result(self.handlers[job_type].resume(r)))
|
|
164
|
+
|
|
165
|
+
def promote(self, job_type: str, job_id: str) -> Ok | Err:
|
|
166
|
+
return self._with_record(
|
|
167
|
+
job_type, job_id, lambda r: self._save_result(self.handlers[job_type].promote(r, self.config_io))
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
def archive(self, job_type: str, job_id: str) -> Ok | Err:
|
|
171
|
+
def run(record: dict[str, Any]) -> Ok | Err:
|
|
172
|
+
result = self.handlers[job_type].archive(record)
|
|
173
|
+
if result.success:
|
|
174
|
+
storage.delete_record(job_type, job_id)
|
|
175
|
+
return result
|
|
176
|
+
|
|
177
|
+
return self._with_record(job_type, job_id, run)
|
|
178
|
+
|
|
179
|
+
def debug(self, job_type: str, job_id: str) -> Ok | Err:
|
|
180
|
+
return self._with_record(job_type, job_id, lambda r: self.handlers[job_type].debug(r))
|
|
181
|
+
|
|
182
|
+
def capabilities(self, job_type: str) -> dict[str, bool]:
|
|
183
|
+
return JOB_CAPABILITIES[job_type]
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def create_job_engine(config_io: ConfigIO | None = None) -> JobEngine:
|
|
187
|
+
return JobEngine(config_io)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Shared presentation helpers for job CLI output (port of operations/jobs/shared/format.ts).
|
|
2
|
+
|
|
3
|
+
Also hosts the small JavaScript-semantics helpers (``toFixed``, ``parseInt``, ``parseFloat``,
|
|
4
|
+
``toLocaleString``) the eval/jobs commands rely on so output matches the npm CLI.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import math
|
|
8
|
+
import re
|
|
9
|
+
from datetime import UTC, datetime
|
|
10
|
+
from decimal import ROUND_HALF_UP, Decimal
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
_MONTHS = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def to_fixed(value: float, digits: int) -> str:
|
|
17
|
+
"""``Number.prototype.toFixed``: exact-value rounding, ties away from zero."""
|
|
18
|
+
if value is None or (isinstance(value, float) and math.isnan(value)):
|
|
19
|
+
return "NaN"
|
|
20
|
+
if isinstance(value, float) and math.isinf(value):
|
|
21
|
+
return "Infinity" if value > 0 else "-Infinity"
|
|
22
|
+
if value == 0:
|
|
23
|
+
value = 0 # (-0).toFixed() has no sign
|
|
24
|
+
quantum = Decimal(1).scaleb(-digits)
|
|
25
|
+
return f"{Decimal(value).quantize(quantum, rounding=ROUND_HALF_UP):f}"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def parse_int(value: Any) -> int | None:
|
|
29
|
+
"""``parseInt(value, 10)``: leading integer digits, else NaN (None)."""
|
|
30
|
+
if value is None:
|
|
31
|
+
return None
|
|
32
|
+
m = re.match(r"^\s*([+-]?\d+)", str(value))
|
|
33
|
+
return int(m.group(1)) if m else None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def parse_float(value: Any) -> float | None:
|
|
37
|
+
"""``parseFloat(value)``: leading decimal number, else NaN (None)."""
|
|
38
|
+
if value is None:
|
|
39
|
+
return None
|
|
40
|
+
m = re.match(r"^\s*([+-]?(?:\d+\.?\d*(?:[eE][+-]?\d+)?|\.\d+(?:[eE][+-]?\d+)?|Infinity))", str(value))
|
|
41
|
+
if not m:
|
|
42
|
+
return None
|
|
43
|
+
text = m.group(1)
|
|
44
|
+
if text.lstrip("+-") == "Infinity":
|
|
45
|
+
return -math.inf if text.startswith("-") else math.inf
|
|
46
|
+
return float(text)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def parse_js_date(value: Any) -> datetime | None:
|
|
50
|
+
"""``new Date(value)`` for ISO strings and epoch-millisecond numbers. None when invalid."""
|
|
51
|
+
if value is None:
|
|
52
|
+
return None
|
|
53
|
+
if isinstance(value, bool):
|
|
54
|
+
return None
|
|
55
|
+
if isinstance(value, (int, float)):
|
|
56
|
+
try:
|
|
57
|
+
return datetime.fromtimestamp(value / 1000, tz=UTC)
|
|
58
|
+
except (OverflowError, OSError, ValueError):
|
|
59
|
+
return None
|
|
60
|
+
text = str(value).strip()
|
|
61
|
+
if not text:
|
|
62
|
+
return None
|
|
63
|
+
try:
|
|
64
|
+
parsed = datetime.fromisoformat(text.replace("Z", "+00:00") if text.endswith("Z") else text)
|
|
65
|
+
except ValueError:
|
|
66
|
+
return None
|
|
67
|
+
if parsed.tzinfo is None:
|
|
68
|
+
# Date-only ISO strings are UTC in JS; date-time strings without offset are local time.
|
|
69
|
+
parsed = parsed.replace(tzinfo=UTC) if len(text) <= 10 else parsed.astimezone()
|
|
70
|
+
return parsed
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def to_locale_string(value: Any) -> str:
|
|
74
|
+
"""``new Date(value).toLocaleString([], {year:'numeric', month:'short', day:'numeric',
|
|
75
|
+
hour:'2-digit', minute:'2-digit'})`` in the en-US locale, e.g. ``Oct 12, 2026, 03:04 PM``."""
|
|
76
|
+
parsed = parse_js_date(value)
|
|
77
|
+
if parsed is None:
|
|
78
|
+
return "Invalid Date"
|
|
79
|
+
local = parsed.astimezone()
|
|
80
|
+
hour12 = local.hour % 12 or 12
|
|
81
|
+
meridiem = "AM" if local.hour < 12 else "PM"
|
|
82
|
+
return f"{_MONTHS[local.month - 1]} {local.day}, {local.year}, {hour12:02d}:{local.minute:02d} {meridiem}"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def format_job_date(iso: str | None) -> str:
|
|
86
|
+
"""Format an ISO timestamp for CLI tables/detail output (shared by all job types)."""
|
|
87
|
+
if not iso:
|
|
88
|
+
return "unknown"
|
|
89
|
+
return to_locale_string(iso)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def iso_now() -> str:
|
|
93
|
+
"""``new Date().toISOString()``."""
|
|
94
|
+
return to_iso(datetime.now(UTC))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def to_iso(dt: datetime) -> str:
|
|
98
|
+
"""``Date.prototype.toISOString`` (UTC, millisecond precision, ``Z`` suffix)."""
|
|
99
|
+
utc = dt.astimezone(UTC)
|
|
100
|
+
return utc.strftime("%Y-%m-%dT%H:%M:%S.") + f"{utc.microsecond // 1000:03d}Z"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def iso_from_ms(ms: float) -> str:
|
|
104
|
+
return to_iso(datetime.fromtimestamp(ms / 1000, tz=UTC))
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Region resolution for jobs (port of operations/jobs/shared/region.ts).
|
|
2
|
+
|
|
3
|
+
Region is resolved once in create() and baked into the stored ARN; refresh/stop/archive parse it
|
|
4
|
+
back out of the ARN.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Sequence
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from agentcore.aws import region as _region
|
|
11
|
+
from agentcore.aws.arn import region_from_arn
|
|
12
|
+
|
|
13
|
+
__all__ = ["field", "region_from_arn", "region_of", "resolve_job_region"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def field(obj: Any, key: str, snake: str | None = None) -> Any:
|
|
17
|
+
"""Read ``key`` from a dict or a model attribute (``snake`` name for pydantic models)."""
|
|
18
|
+
if isinstance(obj, dict):
|
|
19
|
+
return obj.get(key)
|
|
20
|
+
return getattr(obj, snake or key, None)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def resolve_job_region(opts_region: str | None, aws_targets: Sequence[Any]) -> str:
|
|
24
|
+
"""Explicit option -> first deployment target -> detected region."""
|
|
25
|
+
if opts_region:
|
|
26
|
+
return opts_region
|
|
27
|
+
if aws_targets and field(aws_targets[0], "region"):
|
|
28
|
+
return str(field(aws_targets[0], "region"))
|
|
29
|
+
return _region.detect_region().region
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def region_of(arn: str) -> str:
|
|
33
|
+
"""Region parsed from a stored ARN, else the detected region."""
|
|
34
|
+
return region_from_arn(arn) or _region.detect_region().region
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Resolve a deployed agent runtime by name (port of operations/jobs/shared/resolve-agent-state.ts).
|
|
2
|
+
|
|
3
|
+
``deployed_state`` is the camelCase dict form of ``deployed-state.json``.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from agentcore.lib.schemas.io.config_io import to_jsonable
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def deployed_dict(deployed_state: Any) -> dict[str, Any]:
|
|
12
|
+
"""camelCase dict view of a DeployedState model (or pass a dict through)."""
|
|
13
|
+
data = to_jsonable(deployed_state) if not isinstance(deployed_state, dict) else deployed_state
|
|
14
|
+
return data if isinstance(data, dict) else {"targets": {}}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def iter_target_resources(deployed_state: dict[str, Any]):
|
|
18
|
+
for target in (deployed_state.get("targets") or {}).values():
|
|
19
|
+
resources = (target or {}).get("resources")
|
|
20
|
+
if resources:
|
|
21
|
+
yield resources
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def resolve_agent_state(deployed_state: dict[str, Any], agent_name: str) -> dict[str, Any] | None:
|
|
25
|
+
"""The agent runtime across all deployment targets; None if not deployed."""
|
|
26
|
+
for resources in iter_target_resources(deployed_state):
|
|
27
|
+
agent = (resources.get("runtimes") or {}).get(agent_name)
|
|
28
|
+
if agent is not None:
|
|
29
|
+
return agent
|
|
30
|
+
return None
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""Pure file I/O for job records (port of operations/jobs/shared/storage.ts).
|
|
2
|
+
|
|
3
|
+
Layout: ``<configRoot>/.cli/jobs/{STORAGE_DIRS[type]}/{id}.json``, written as
|
|
4
|
+
``JSON.stringify(record, null, 2)`` so the npm CLI and this port read each other's files.
|
|
5
|
+
|
|
6
|
+
- atomic writes (temp file + rename),
|
|
7
|
+
- per-file parse guard in ``list_records`` (a corrupt file is skipped),
|
|
8
|
+
- ``assert_safe_id`` path-traversal guard; the content ``id`` is authoritative over the filename.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from agentcore.lib import CLI_SYSTEM_DIR, NoProjectError, find_config_root
|
|
17
|
+
from agentcore.lib.utils.json_format import to_json_string
|
|
18
|
+
from agentcore.operations.jobs.shared.constants import STORAGE_DIRS
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _cli_dir() -> str:
|
|
22
|
+
config_root = find_config_root()
|
|
23
|
+
if not config_root:
|
|
24
|
+
raise NoProjectError()
|
|
25
|
+
return os.path.join(config_root, CLI_SYSTEM_DIR)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def dir_for(job_type: str) -> str:
|
|
29
|
+
return os.path.join(_cli_dir(), "jobs", STORAGE_DIRS[job_type])
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _file_for(job_type: str, job_id: str) -> str:
|
|
33
|
+
return os.path.join(dir_for(job_type), f"{job_id}.json")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def assert_safe_id(job_id: str) -> None:
|
|
37
|
+
"""Reject ids that could escape the storage directory."""
|
|
38
|
+
if not job_id or re.search(r"[/\\]", job_id):
|
|
39
|
+
raise ValueError("Invalid job id: must be non-empty and contain no path separators")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _is_job_record_of_type(value: Any, job_type: str) -> bool:
|
|
43
|
+
if not isinstance(value, dict):
|
|
44
|
+
return False
|
|
45
|
+
job_id = value.get("id")
|
|
46
|
+
return value.get("type") == job_type and isinstance(job_id, str) and len(job_id) > 0
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def drop_undefined(value: Any) -> Any:
|
|
50
|
+
"""Recursively drop ``None`` dict values (JS ``undefined`` is omitted by JSON.stringify)."""
|
|
51
|
+
if isinstance(value, dict):
|
|
52
|
+
return {k: drop_undefined(v) for k, v in value.items() if v is not None}
|
|
53
|
+
if isinstance(value, list):
|
|
54
|
+
return [drop_undefined(v) for v in value]
|
|
55
|
+
return value
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def record_json(record: dict[str, Any], indent: int | None = 2) -> str:
|
|
59
|
+
return to_json_string(drop_undefined(record), indent)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def save_record(record: dict[str, Any]) -> str:
|
|
63
|
+
"""Persist a record atomically (temp file + rename). Returns the file path."""
|
|
64
|
+
assert_safe_id(record["id"])
|
|
65
|
+
directory = dir_for(record["type"])
|
|
66
|
+
os.makedirs(directory, exist_ok=True)
|
|
67
|
+
file_path = _file_for(record["type"], record["id"])
|
|
68
|
+
tmp_path = f"{file_path}.tmp"
|
|
69
|
+
with open(tmp_path, "w", encoding="utf-8", newline="") as fh:
|
|
70
|
+
fh.write(record_json(record))
|
|
71
|
+
os.replace(tmp_path, file_path)
|
|
72
|
+
return file_path
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def load_record(job_type: str, job_id: str) -> dict[str, Any] | None:
|
|
76
|
+
"""One record, or None if missing, unparseable, or a legacy/foreign shape."""
|
|
77
|
+
assert_safe_id(job_id)
|
|
78
|
+
file_path = _file_for(job_type, job_id)
|
|
79
|
+
if not os.path.exists(file_path):
|
|
80
|
+
return None
|
|
81
|
+
try:
|
|
82
|
+
with open(file_path, encoding="utf-8") as fh:
|
|
83
|
+
parsed = json.load(fh)
|
|
84
|
+
except (OSError, ValueError):
|
|
85
|
+
return None
|
|
86
|
+
return parsed if _is_job_record_of_type(parsed, job_type) else None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def list_records(job_type: str | None = None) -> list[dict[str, Any]]:
|
|
90
|
+
"""Records for one type (or all types). Skips corrupt/legacy files; never raises on a bad file."""
|
|
91
|
+
types = [job_type] if job_type else list(STORAGE_DIRS)
|
|
92
|
+
records: list[dict[str, Any]] = []
|
|
93
|
+
for t in types:
|
|
94
|
+
directory = dir_for(t)
|
|
95
|
+
if not os.path.isdir(directory):
|
|
96
|
+
continue
|
|
97
|
+
for name in os.listdir(directory):
|
|
98
|
+
if not name.endswith(".json"):
|
|
99
|
+
continue
|
|
100
|
+
try:
|
|
101
|
+
with open(os.path.join(directory, name), encoding="utf-8") as fh:
|
|
102
|
+
parsed = json.load(fh)
|
|
103
|
+
except (OSError, ValueError):
|
|
104
|
+
continue
|
|
105
|
+
if _is_job_record_of_type(parsed, t):
|
|
106
|
+
records.append(parsed)
|
|
107
|
+
return records
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def delete_record(job_type: str, job_id: str) -> bool:
|
|
111
|
+
"""Delete the local record file. True if it existed and was removed."""
|
|
112
|
+
assert_safe_id(job_id)
|
|
113
|
+
file_path = _file_for(job_type, job_id)
|
|
114
|
+
if not os.path.exists(file_path):
|
|
115
|
+
return False
|
|
116
|
+
os.remove(file_path)
|
|
117
|
+
return True
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Block until a job reaches a terminal state (port of operations/jobs/shared/wait.ts)."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from agentcore.operations.jobs.shared.constants import is_terminal
|
|
8
|
+
|
|
9
|
+
DEFAULT_POLL_INTERVAL_MS = 5000
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def wait_for_terminal(
|
|
13
|
+
engine: Any,
|
|
14
|
+
job_type: str,
|
|
15
|
+
job_id: str,
|
|
16
|
+
*,
|
|
17
|
+
poll_interval_ms: int = DEFAULT_POLL_INTERVAL_MS,
|
|
18
|
+
on_tick: Callable[[str], None] | None = None,
|
|
19
|
+
sleep: Callable[[float], None] = time.sleep,
|
|
20
|
+
) -> dict[str, Any] | None:
|
|
21
|
+
"""Poll ``engine.get`` until terminal; None if the job vanished from local storage."""
|
|
22
|
+
while True:
|
|
23
|
+
record = engine.get(job_type, job_id)
|
|
24
|
+
if record is None:
|
|
25
|
+
return None
|
|
26
|
+
if on_tick:
|
|
27
|
+
on_tick(record["status"])
|
|
28
|
+
if is_terminal(record):
|
|
29
|
+
return record
|
|
30
|
+
sleep(poll_interval_ms / 1000)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Knowledge base operations (port of upstream ``src/cli/operations/knowledge-base``)."""
|
|
2
|
+
|
|
3
|
+
from agentcore.operations.knowledge_base.connector_config import (
|
|
4
|
+
CONNECTOR_TYPE_BY_FLAG,
|
|
5
|
+
DATA_SOURCE_TYPE_FLAGS,
|
|
6
|
+
FLAG_BY_CONNECTOR_TYPE,
|
|
7
|
+
ConnectorConfigReadResult,
|
|
8
|
+
DataSourceTypeFlag,
|
|
9
|
+
DataSourceWireType,
|
|
10
|
+
extract_secret_arn,
|
|
11
|
+
flag_to_wire_type,
|
|
12
|
+
is_connector_config_type,
|
|
13
|
+
read_connector_config,
|
|
14
|
+
)
|
|
15
|
+
from agentcore.operations.knowledge_base.hydrate_data_sources import (
|
|
16
|
+
hydrate_knowledge_base_data_sources,
|
|
17
|
+
uri_hash_prefix,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"CONNECTOR_TYPE_BY_FLAG",
|
|
22
|
+
"DATA_SOURCE_TYPE_FLAGS",
|
|
23
|
+
"FLAG_BY_CONNECTOR_TYPE",
|
|
24
|
+
"ConnectorConfigReadResult",
|
|
25
|
+
"DataSourceTypeFlag",
|
|
26
|
+
"DataSourceWireType",
|
|
27
|
+
"extract_secret_arn",
|
|
28
|
+
"flag_to_wire_type",
|
|
29
|
+
"hydrate_knowledge_base_data_sources",
|
|
30
|
+
"is_connector_config_type",
|
|
31
|
+
"read_connector_config",
|
|
32
|
+
"uri_hash_prefix",
|
|
33
|
+
]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Connector-config flag mapping and file validation (port of operations/knowledge-base/connector-config.ts)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Any, Final, Literal
|
|
9
|
+
|
|
10
|
+
DataSourceTypeFlag = Literal["s3", "web-crawler", "confluence", "sharepoint", "onedrive", "google-drive"]
|
|
11
|
+
DataSourceWireType = Literal["S3", "WEB", "CONFLUENCE", "SHAREPOINT", "ONEDRIVE", "GOOGLEDRIVE"]
|
|
12
|
+
|
|
13
|
+
# User-facing `--data-source-type` flag values, including S3 (the default).
|
|
14
|
+
DATA_SOURCE_TYPE_FLAGS: Final[tuple[str, ...]] = (
|
|
15
|
+
"s3",
|
|
16
|
+
"web-crawler",
|
|
17
|
+
"confluence",
|
|
18
|
+
"sharepoint",
|
|
19
|
+
"onedrive",
|
|
20
|
+
"google-drive",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# The single translation table: user flag -> wire `type`.
|
|
24
|
+
CONNECTOR_TYPE_BY_FLAG: Final[dict[str, str]] = {
|
|
25
|
+
"s3": "S3",
|
|
26
|
+
"web-crawler": "WEB",
|
|
27
|
+
"confluence": "CONFLUENCE",
|
|
28
|
+
"sharepoint": "SHAREPOINT",
|
|
29
|
+
"onedrive": "ONEDRIVE",
|
|
30
|
+
"google-drive": "GOOGLEDRIVE",
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Inverse table, for rendering a wire type back as a user-facing flag.
|
|
34
|
+
FLAG_BY_CONNECTOR_TYPE: Final[dict[str, str]] = {wire: flag for flag, wire in CONNECTOR_TYPE_BY_FLAG.items()}
|
|
35
|
+
|
|
36
|
+
# Connector wire types that require a secretArn unless explicitly NO_AUTH.
|
|
37
|
+
_SECRET_BEARING: Final = frozenset({"CONFLUENCE", "SHAREPOINT", "ONEDRIVE", "GOOGLEDRIVE"})
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def flag_to_wire_type(flag: str) -> str:
|
|
41
|
+
wire = CONNECTOR_TYPE_BY_FLAG.get(flag)
|
|
42
|
+
if not wire:
|
|
43
|
+
raise ValueError(f'Unknown data source type "{flag}". Expected one of: {", ".join(DATA_SOURCE_TYPE_FLAGS)}.')
|
|
44
|
+
return wire
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def is_connector_config_type(wire: str) -> bool:
|
|
48
|
+
"""True for every wire type that uses a connectorConfigFile (i.e. not S3)."""
|
|
49
|
+
return wire != "S3" and wire in FLAG_BY_CONNECTOR_TYPE
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class ConnectorConfigReadResult:
|
|
54
|
+
parsed: dict[str, Any]
|
|
55
|
+
"""The parsed connectorParameters object, passed through to the L3 verbatim."""
|
|
56
|
+
warnings: list[str] = field(default_factory=list)
|
|
57
|
+
"""Non-fatal advisories surfaced to the user (e.g. missing secretArn)."""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def read_connector_config(path: str, declared_type: str) -> ConnectorConfigReadResult:
|
|
61
|
+
"""Read a ``--connector-config`` JSON file and validate it lightly.
|
|
62
|
+
|
|
63
|
+
Only checks: the file exists, parses, carries a ``type`` matching the declared connector type,
|
|
64
|
+
and (for auth connectors) warns when no secretArn is present.
|
|
65
|
+
"""
|
|
66
|
+
resolved = os.path.abspath(path)
|
|
67
|
+
if not os.path.exists(resolved):
|
|
68
|
+
raise ValueError(f"Connector config file not found: {path}")
|
|
69
|
+
try:
|
|
70
|
+
with open(resolved, encoding="utf-8") as fh:
|
|
71
|
+
parsed = json.load(fh)
|
|
72
|
+
except (ValueError, UnicodeDecodeError):
|
|
73
|
+
raise ValueError(f"Connector config file is not valid JSON: {path}") from None
|
|
74
|
+
if not parsed or not isinstance(parsed, dict):
|
|
75
|
+
raise ValueError(f"Connector config file must be a JSON object: {path}")
|
|
76
|
+
if not isinstance(parsed.get("type"), str):
|
|
77
|
+
raise ValueError(f'Connector config file is missing a "type" field: {path}')
|
|
78
|
+
if parsed["type"] != declared_type:
|
|
79
|
+
raise ValueError(
|
|
80
|
+
f'Connector config "type" ({parsed["type"]}) does not match the declared data source type '
|
|
81
|
+
f"({declared_type}) in {path}."
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
warnings: list[str] = []
|
|
85
|
+
cc = parsed.get("connectionConfiguration")
|
|
86
|
+
cc = cc if isinstance(cc, dict) else None
|
|
87
|
+
has_secret = cc is not None and isinstance(cc.get("secretArn"), str) and bool(cc.get("secretArn"))
|
|
88
|
+
if declared_type in _SECRET_BEARING and not has_secret:
|
|
89
|
+
warnings.append(
|
|
90
|
+
f"Connector config {path} has no connectionConfiguration.secretArn; {declared_type} ingestion will "
|
|
91
|
+
"fail at deploy until credentials are provided."
|
|
92
|
+
)
|
|
93
|
+
if declared_type == "WEB":
|
|
94
|
+
auth_type = cc.get("authType") if cc is not None and isinstance(cc.get("authType"), str) else None
|
|
95
|
+
if auth_type and auth_type != "NO_AUTH" and not has_secret:
|
|
96
|
+
warnings.append(f"Connector config {path} uses authType {auth_type} but has no secretArn.")
|
|
97
|
+
|
|
98
|
+
return ConnectorConfigReadResult(parsed=parsed, warnings=warnings)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def extract_secret_arn(parsed: dict[str, Any]) -> str | None:
|
|
102
|
+
"""Pull connectionConfiguration.secretArn from a parsed connector config, if present."""
|
|
103
|
+
cc = parsed.get("connectionConfiguration")
|
|
104
|
+
arn = cc.get("secretArn") if isinstance(cc, dict) else None
|
|
105
|
+
return arn if isinstance(arn, str) and arn else None
|