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.
Files changed (655) hide show
  1. agentcore/__init__.py +1 -0
  2. agentcore/agent_inspector/NOTICE +9 -0
  3. agentcore/agent_inspector/favicon.svg +60 -0
  4. agentcore/agent_inspector/index.css +1 -0
  5. agentcore/agent_inspector/index.html +14 -0
  6. agentcore/agent_inspector/index.js +289 -0
  7. agentcore/assets/AGENTS.md +60 -0
  8. agentcore/assets/README.md +108 -0
  9. agentcore/assets/agents/AGENTS.md +218 -0
  10. agentcore/assets/cdk/.prettierrc +8 -0
  11. agentcore/assets/cdk/README.md +26 -0
  12. agentcore/assets/cdk/bin/cdk.ts +216 -0
  13. agentcore/assets/cdk/cdk.json +88 -0
  14. agentcore/assets/cdk/gitignore.template +9 -0
  15. agentcore/assets/cdk/jest.config.js +9 -0
  16. agentcore/assets/cdk/lib/cdk-stack.ts +291 -0
  17. agentcore/assets/cdk/npmignore.template +6 -0
  18. agentcore/assets/cdk/package.json +30 -0
  19. agentcore/assets/cdk/test/cdk.test.ts +31 -0
  20. agentcore/assets/cdk/tsconfig.json +28 -0
  21. agentcore/assets/container/python/Dockerfile +47 -0
  22. agentcore/assets/container/python/dockerignore.template +27 -0
  23. agentcore/assets/container/typescript/Dockerfile +25 -0
  24. agentcore/assets/container/typescript/dockerignore.template +24 -0
  25. agentcore/assets/datasets/predefined-v1.jsonl +3 -0
  26. agentcore/assets/datasets/simulated-v1.jsonl +3 -0
  27. agentcore/assets/evaluators/autoevals-lambda/execution-role-policy.json +15 -0
  28. agentcore/assets/evaluators/autoevals-lambda/lambda_function.py +37 -0
  29. agentcore/assets/evaluators/autoevals-lambda/pyproject.toml +22 -0
  30. agentcore/assets/evaluators/deepeval-lambda/execution-role-policy.json +15 -0
  31. agentcore/assets/evaluators/deepeval-lambda/lambda_function.py +29 -0
  32. agentcore/assets/evaluators/deepeval-lambda/pyproject.toml +19 -0
  33. agentcore/assets/evaluators/python-lambda/execution-role-policy.json +10 -0
  34. agentcore/assets/evaluators/python-lambda/lambda_function.py +19 -0
  35. agentcore/assets/evaluators/python-lambda/pyproject.toml +15 -0
  36. agentcore/assets/harness/invoke.py.template +74 -0
  37. agentcore/assets/mcp/python/README.md +27 -0
  38. agentcore/assets/mcp/python/pyproject.toml +22 -0
  39. agentcore/assets/mcp/python/server.py +117 -0
  40. agentcore/assets/mcp/python-lambda/README.md +22 -0
  41. agentcore/assets/mcp/python-lambda/handler.py +144 -0
  42. agentcore/assets/mcp/python-lambda/pyproject.toml +15 -0
  43. agentcore/assets/python/a2a/googleadk/base/README.md +22 -0
  44. agentcore/assets/python/a2a/googleadk/base/gitignore.template +41 -0
  45. agentcore/assets/python/a2a/googleadk/base/main.py +124 -0
  46. agentcore/assets/python/a2a/googleadk/base/model/__init__.py +1 -0
  47. agentcore/assets/python/a2a/googleadk/base/model/load.py +41 -0
  48. agentcore/assets/python/a2a/googleadk/base/pyproject.toml +22 -0
  49. agentcore/assets/python/a2a/langchain_langgraph/base/README.md +22 -0
  50. agentcore/assets/python/a2a/langchain_langgraph/base/gitignore.template +41 -0
  51. agentcore/assets/python/a2a/langchain_langgraph/base/main.py +144 -0
  52. agentcore/assets/python/a2a/langchain_langgraph/base/model/__init__.py +1 -0
  53. agentcore/assets/python/a2a/langchain_langgraph/base/model/load.py +123 -0
  54. agentcore/assets/python/a2a/langchain_langgraph/base/pyproject.toml +26 -0
  55. agentcore/assets/python/a2a/strands/base/README.md +22 -0
  56. agentcore/assets/python/a2a/strands/base/gitignore.template +41 -0
  57. agentcore/assets/python/a2a/strands/base/main.py +113 -0
  58. agentcore/assets/python/a2a/strands/base/model/__init__.py +1 -0
  59. agentcore/assets/python/a2a/strands/base/model/load.py +123 -0
  60. agentcore/assets/python/a2a/strands/base/pyproject.toml +23 -0
  61. agentcore/assets/python/a2a/strands/capabilities/memory/__init__.py +1 -0
  62. agentcore/assets/python/a2a/strands/capabilities/memory/session.py +46 -0
  63. agentcore/assets/python/agui/googleadk/base/README.md +30 -0
  64. agentcore/assets/python/agui/googleadk/base/gitignore.template +41 -0
  65. agentcore/assets/python/agui/googleadk/base/main.py +91 -0
  66. agentcore/assets/python/agui/googleadk/base/model/__init__.py +1 -0
  67. agentcore/assets/python/agui/googleadk/base/model/load.py +41 -0
  68. agentcore/assets/python/agui/googleadk/base/pyproject.toml +25 -0
  69. agentcore/assets/python/agui/langchain_langgraph/base/README.md +22 -0
  70. agentcore/assets/python/agui/langchain_langgraph/base/gitignore.template +41 -0
  71. agentcore/assets/python/agui/langchain_langgraph/base/main.py +130 -0
  72. agentcore/assets/python/agui/langchain_langgraph/base/model/__init__.py +1 -0
  73. agentcore/assets/python/agui/langchain_langgraph/base/model/load.py +123 -0
  74. agentcore/assets/python/agui/langchain_langgraph/base/pyproject.toml +31 -0
  75. agentcore/assets/python/agui/strands/base/README.md +22 -0
  76. agentcore/assets/python/agui/strands/base/gitignore.template +41 -0
  77. agentcore/assets/python/agui/strands/base/main.py +105 -0
  78. agentcore/assets/python/agui/strands/base/model/__init__.py +1 -0
  79. agentcore/assets/python/agui/strands/base/model/load.py +123 -0
  80. agentcore/assets/python/agui/strands/base/pyproject.toml +27 -0
  81. agentcore/assets/python/agui/strands/capabilities/memory/__init__.py +1 -0
  82. agentcore/assets/python/agui/strands/capabilities/memory/session.py +46 -0
  83. agentcore/assets/python/http/autogen/base/README.md +45 -0
  84. agentcore/assets/python/http/autogen/base/gitignore.template +41 -0
  85. agentcore/assets/python/http/autogen/base/main.py +145 -0
  86. agentcore/assets/python/http/autogen/base/mcp_client/__init__.py +1 -0
  87. agentcore/assets/python/http/autogen/base/mcp_client/client.py +28 -0
  88. agentcore/assets/python/http/autogen/base/model/__init__.py +1 -0
  89. agentcore/assets/python/http/autogen/base/model/load.py +136 -0
  90. agentcore/assets/python/http/autogen/base/pyproject.toml +34 -0
  91. agentcore/assets/python/http/bma/base/Dockerfile +41 -0
  92. agentcore/assets/python/http/bma/base/README.md +178 -0
  93. agentcore/assets/python/http/bma/base/client.py +200 -0
  94. agentcore/assets/python/http/bma/base/lifecycle/server.py +641 -0
  95. agentcore/assets/python/http/bma/base/otel/collector.yaml +69 -0
  96. agentcore/assets/python/http/bma/base/plugins/acr-report/.codex-plugin/plugin.json +6 -0
  97. agentcore/assets/python/http/bma/base/plugins/acr-report/skills/acr-report/SKILL.md +16 -0
  98. agentcore/assets/python/http/bma/base/policies/bma-acr-policy.json +11 -0
  99. agentcore/assets/python/http/bma/base/policies/bma-session-policy.json +35 -0
  100. agentcore/assets/python/http/bma/base/policies/bma-session-trust.json +20 -0
  101. agentcore/assets/python/http/bma/base/pyproject.toml +21 -0
  102. agentcore/assets/python/http/googleadk/base/README.md +45 -0
  103. agentcore/assets/python/http/googleadk/base/gitignore.template +41 -0
  104. agentcore/assets/python/http/googleadk/base/main.py +207 -0
  105. agentcore/assets/python/http/googleadk/base/mcp_client/__init__.py +1 -0
  106. agentcore/assets/python/http/googleadk/base/mcp_client/client.py +75 -0
  107. agentcore/assets/python/http/googleadk/base/model/__init__.py +1 -0
  108. agentcore/assets/python/http/googleadk/base/model/load.py +41 -0
  109. agentcore/assets/python/http/googleadk/base/pyproject.toml +24 -0
  110. agentcore/assets/python/http/langchain_langgraph/base/README.md +45 -0
  111. agentcore/assets/python/http/langchain_langgraph/base/gitignore.template +41 -0
  112. agentcore/assets/python/http/langchain_langgraph/base/main.py +227 -0
  113. agentcore/assets/python/http/langchain_langgraph/base/mcp_client/__init__.py +1 -0
  114. agentcore/assets/python/http/langchain_langgraph/base/mcp_client/client.py +79 -0
  115. agentcore/assets/python/http/langchain_langgraph/base/model/__init__.py +1 -0
  116. agentcore/assets/python/http/langchain_langgraph/base/model/load.py +123 -0
  117. agentcore/assets/python/http/langchain_langgraph/base/pyproject.toml +38 -0
  118. agentcore/assets/python/http/openaiagents/base/README.md +45 -0
  119. agentcore/assets/python/http/openaiagents/base/gitignore.template +41 -0
  120. agentcore/assets/python/http/openaiagents/base/main.py +200 -0
  121. agentcore/assets/python/http/openaiagents/base/mcp_client/__init__.py +1 -0
  122. agentcore/assets/python/http/openaiagents/base/mcp_client/client.py +74 -0
  123. agentcore/assets/python/http/openaiagents/base/model/__init__.py +1 -0
  124. agentcore/assets/python/http/openaiagents/base/model/load.py +37 -0
  125. agentcore/assets/python/http/openaiagents/base/pyproject.toml +21 -0
  126. agentcore/assets/python/http/strands/base/README.md +46 -0
  127. agentcore/assets/python/http/strands/base/gitignore.template +41 -0
  128. agentcore/assets/python/http/strands/base/main.py +714 -0
  129. agentcore/assets/python/http/strands/base/mcp_client/__init__.py +1 -0
  130. agentcore/assets/python/http/strands/base/mcp_client/client.py +116 -0
  131. agentcore/assets/python/http/strands/base/model/__init__.py +1 -0
  132. agentcore/assets/python/http/strands/base/model/load.py +239 -0
  133. agentcore/assets/python/http/strands/base/model/mantle_compat.py +21 -0
  134. agentcore/assets/python/http/strands/base/pyproject.toml +31 -0
  135. agentcore/assets/python/http/strands/base/skills/fetcher.py +279 -0
  136. agentcore/assets/python/http/strands/capabilities/execution-limits/hooks/execution_limits.py +54 -0
  137. agentcore/assets/python/http/strands/capabilities/memory/__init__.py +1 -0
  138. agentcore/assets/python/http/strands/capabilities/memory/session.py +47 -0
  139. agentcore/assets/python/http/strands/capabilities/payments/__init__.py +4 -0
  140. agentcore/assets/python/http/strands/capabilities/payments/payments.py +142 -0
  141. agentcore/assets/python/mcp/standalone/base/README.md +36 -0
  142. agentcore/assets/python/mcp/standalone/base/gitignore.template +41 -0
  143. agentcore/assets/python/mcp/standalone/base/main.py +83 -0
  144. agentcore/assets/python/mcp/standalone/base/pyproject.toml +16 -0
  145. agentcore/assets/typescript/.gitkeep +0 -0
  146. agentcore/assets/typescript/http/strands/base/README.md +42 -0
  147. agentcore/assets/typescript/http/strands/base/gitignore.template +22 -0
  148. agentcore/assets/typescript/http/strands/base/main.ts +149 -0
  149. agentcore/assets/typescript/http/strands/base/mcp_client/client.ts +11 -0
  150. agentcore/assets/typescript/http/strands/base/model/load.ts +102 -0
  151. agentcore/assets/typescript/http/strands/base/package.json +38 -0
  152. agentcore/assets/typescript/http/strands/base/tsconfig.json +19 -0
  153. agentcore/assets/typescript/http/strands/capabilities/memory/memory.ts +52 -0
  154. agentcore/assets/typescript/http/vercelai/base/README.md +42 -0
  155. agentcore/assets/typescript/http/vercelai/base/gitignore.template +22 -0
  156. agentcore/assets/typescript/http/vercelai/base/main.ts +70 -0
  157. agentcore/assets/typescript/http/vercelai/base/model/load.ts +121 -0
  158. agentcore/assets/typescript/http/vercelai/base/package.json +35 -0
  159. agentcore/assets/typescript/http/vercelai/base/tsconfig.json +19 -0
  160. agentcore/aws/__init__.py +263 -0
  161. agentcore/aws/_aws_errors.py +72 -0
  162. agentcore/aws/_http.py +176 -0
  163. agentcore/aws/_util.py +37 -0
  164. agentcore/aws/account.py +165 -0
  165. agentcore/aws/agentcore.py +971 -0
  166. agentcore/aws/agentcore_ab_tests.py +230 -0
  167. agentcore/aws/agentcore_batch_evaluation.py +227 -0
  168. agentcore/aws/agentcore_config_bundles.py +220 -0
  169. agentcore/aws/agentcore_control.py +994 -0
  170. agentcore/aws/agentcore_datasets.py +222 -0
  171. agentcore/aws/agentcore_harness.py +330 -0
  172. agentcore/aws/agentcore_payments.py +430 -0
  173. agentcore/aws/agentcore_recommendation.py +140 -0
  174. agentcore/aws/agui_parser.py +131 -0
  175. agentcore/aws/agui_types.py +342 -0
  176. agentcore/aws/api_client.py +87 -0
  177. agentcore/aws/arn.py +18 -0
  178. agentcore/aws/aws_context.py +23 -0
  179. agentcore/aws/bedrock.py +44 -0
  180. agentcore/aws/bedrock_agent.py +129 -0
  181. agentcore/aws/bedrock_import.py +252 -0
  182. agentcore/aws/bedrock_import_types.py +111 -0
  183. agentcore/aws/cloudwatch.py +136 -0
  184. agentcore/aws/connect_shell.py +266 -0
  185. agentcore/aws/iam.py +41 -0
  186. agentcore/aws/partition.py +58 -0
  187. agentcore/aws/policy_generation.py +116 -0
  188. agentcore/aws/region.py +54 -0
  189. agentcore/aws/retry.py +27 -0
  190. agentcore/aws/shell_framer.py +136 -0
  191. agentcore/aws/stage_endpoint.py +39 -0
  192. agentcore/aws/target_region.py +54 -0
  193. agentcore/aws/transaction_search.py +97 -0
  194. agentcore/cdk/__init__.py +10 -0
  195. agentcore/cdk/constants.py +13 -0
  196. agentcore/cdk/local_cdk_project.py +48 -0
  197. agentcore/cdk/toolkit.py +706 -0
  198. agentcore/cli/__init__.py +0 -0
  199. agentcore/cli/commands/__init__.py +0 -0
  200. agentcore/cli/commands/_jobs_common.py +39 -0
  201. agentcore/cli/commands/_run_wizards.py +639 -0
  202. agentcore/cli/commands/add/__init__.py +37 -0
  203. agentcore/cli/commands/add/_commander.py +52 -0
  204. agentcore/cli/commands/add/_common.py +47 -0
  205. agentcore/cli/commands/add/agent_wizard.py +528 -0
  206. agentcore/cli/commands/add/auth_options.py +154 -0
  207. agentcore/cli/commands/add/skill_action.py +105 -0
  208. agentcore/cli/commands/add/skill_command.py +87 -0
  209. agentcore/cli/commands/add/tool_action.py +160 -0
  210. agentcore/cli/commands/add/tool_command.py +117 -0
  211. agentcore/cli/commands/add/validate.py +333 -0
  212. agentcore/cli/commands/capacity_provider/__init__.py +86 -0
  213. agentcore/cli/commands/capacity_provider/action.py +114 -0
  214. agentcore/cli/commands/capacity_provider/constants.py +22 -0
  215. agentcore/cli/commands/config.py +91 -0
  216. agentcore/cli/commands/config_bundle.py +251 -0
  217. agentcore/cli/commands/create/__init__.py +643 -0
  218. agentcore/cli/commands/create/action.py +406 -0
  219. agentcore/cli/commands/create/dependencies.py +91 -0
  220. agentcore/cli/commands/create/harness_validate.py +82 -0
  221. agentcore/cli/commands/create/validate.py +195 -0
  222. agentcore/cli/commands/create/wizard.py +127 -0
  223. agentcore/cli/commands/dataset.py +119 -0
  224. agentcore/cli/commands/deploy/__init__.py +31 -0
  225. agentcore/cli/commands/deploy/_guards.py +25 -0
  226. agentcore/cli/commands/deploy/actions.py +840 -0
  227. agentcore/cli/commands/deploy/command.py +349 -0
  228. agentcore/cli/commands/deploy/progress.py +115 -0
  229. agentcore/cli/commands/deploy/types.py +68 -0
  230. agentcore/cli/commands/deploy/utils.py +43 -0
  231. agentcore/cli/commands/deploy/validate.py +21 -0
  232. agentcore/cli/commands/dev/__init__.py +5 -0
  233. agentcore/cli/commands/dev/_deps.py +50 -0
  234. agentcore/cli/commands/dev/browser_mode.py +270 -0
  235. agentcore/cli/commands/dev/command.py +450 -0
  236. agentcore/cli/commands/dev/terminal_mode.py +379 -0
  237. agentcore/cli/commands/exec/__init__.py +29 -0
  238. agentcore/cli/commands/exec/action.py +442 -0
  239. agentcore/cli/commands/exec/command.py +206 -0
  240. agentcore/cli/commands/exec/types.py +35 -0
  241. agentcore/cli/commands/export/__init__.py +114 -0
  242. agentcore/cli/commands/export/constants.py +21 -0
  243. agentcore/cli/commands/export/fetch_harness_spec.py +234 -0
  244. agentcore/cli/commands/export/harness_action.py +385 -0
  245. agentcore/cli/commands/export/harness_mapper.py +868 -0
  246. agentcore/cli/commands/export/harness_resolver.py +95 -0
  247. agentcore/cli/commands/export/types.py +90 -0
  248. agentcore/cli/commands/export/wizard.py +97 -0
  249. agentcore/cli/commands/feedback/__init__.py +69 -0
  250. agentcore/cli/commands/feedback/action.py +30 -0
  251. agentcore/cli/commands/feedback/consent_prompt.py +35 -0
  252. agentcore/cli/commands/feedback/wizard.py +49 -0
  253. agentcore/cli/commands/fetch/__init__.py +69 -0
  254. agentcore/cli/commands/fetch/action.py +62 -0
  255. agentcore/cli/commands/help.py +65 -0
  256. agentcore/cli/commands/import_/__init__.py +167 -0
  257. agentcore/cli/commands/import_/_js.py +72 -0
  258. agentcore/cli/commands/import_/actions.py +457 -0
  259. agentcore/cli/commands/import_/constants.py +45 -0
  260. agentcore/cli/commands/import_/import_evaluator.py +140 -0
  261. agentcore/cli/commands/import_/import_gateway.py +520 -0
  262. agentcore/cli/commands/import_/import_memory.py +128 -0
  263. agentcore/cli/commands/import_/import_online_eval.py +165 -0
  264. agentcore/cli/commands/import_/import_pipeline.py +145 -0
  265. agentcore/cli/commands/import_/import_runtime.py +214 -0
  266. agentcore/cli/commands/import_/import_utils.py +410 -0
  267. agentcore/cli/commands/import_/phase1_update.py +110 -0
  268. agentcore/cli/commands/import_/phase2_import.py +206 -0
  269. agentcore/cli/commands/import_/resource_import.py +228 -0
  270. agentcore/cli/commands/import_/template_utils.py +148 -0
  271. agentcore/cli/commands/import_/types.py +150 -0
  272. agentcore/cli/commands/import_/yaml_parser.py +265 -0
  273. agentcore/cli/commands/init.py +196 -0
  274. agentcore/cli/commands/invoke/__init__.py +32 -0
  275. agentcore/cli/commands/invoke/_deps.py +73 -0
  276. agentcore/cli/commands/invoke/action.py +840 -0
  277. agentcore/cli/commands/invoke/command.py +490 -0
  278. agentcore/cli/commands/invoke/constants.py +40 -0
  279. agentcore/cli/commands/invoke/guards.py +23 -0
  280. agentcore/cli/commands/invoke/interactive.py +604 -0
  281. agentcore/cli/commands/invoke/resolve.py +149 -0
  282. agentcore/cli/commands/invoke/resolve_prompt.py +60 -0
  283. agentcore/cli/commands/invoke/types.py +61 -0
  284. agentcore/cli/commands/invoke/validate.py +33 -0
  285. agentcore/cli/commands/job_actions.py +239 -0
  286. agentcore/cli/commands/job_history.py +380 -0
  287. agentcore/cli/commands/logs/__init__.py +53 -0
  288. agentcore/cli/commands/logs/action.py +159 -0
  289. agentcore/cli/commands/logs/filter_pattern.py +17 -0
  290. agentcore/cli/commands/logs/guards.py +51 -0
  291. agentcore/cli/commands/logs_evals.py +42 -0
  292. agentcore/cli/commands/package.py +118 -0
  293. agentcore/cli/commands/remove/__init__.py +172 -0
  294. agentcore/cli/commands/remove/skill_command.py +131 -0
  295. agentcore/cli/commands/remove/tool_command.py +59 -0
  296. agentcore/cli/commands/run.py +808 -0
  297. agentcore/cli/commands/run_ingest.py +97 -0
  298. agentcore/cli/commands/shared/__init__.py +0 -0
  299. agentcore/cli/commands/shared/arn_utils.py +9 -0
  300. agentcore/cli/commands/shared/filesystem_utils.py +421 -0
  301. agentcore/cli/commands/shared/header_utils.py +87 -0
  302. agentcore/cli/commands/shared/indexed_key_parser.py +76 -0
  303. agentcore/cli/commands/shared/lifecycle_utils.py +72 -0
  304. agentcore/cli/commands/shared/region_utils.py +20 -0
  305. agentcore/cli/commands/shared/vpc_utils.py +99 -0
  306. agentcore/cli/commands/status/__init__.py +30 -0
  307. agentcore/cli/commands/status/_guards.py +25 -0
  308. agentcore/cli/commands/status/action.py +741 -0
  309. agentcore/cli/commands/status/command.py +321 -0
  310. agentcore/cli/commands/status/constants.py +36 -0
  311. agentcore/cli/commands/status/format_knowledge_base.py +111 -0
  312. agentcore/cli/commands/telemetry.py +79 -0
  313. agentcore/cli/commands/traces/__init__.py +155 -0
  314. agentcore/cli/commands/traces/action.py +123 -0
  315. agentcore/cli/commands/update/__init__.py +63 -0
  316. agentcore/cli/commands/update/action.py +164 -0
  317. agentcore/cli/commands/validate.py +165 -0
  318. agentcore/cli/constants.py +96 -0
  319. agentcore/cli/errors.py +118 -0
  320. agentcore/cli/external_requirements/__init__.py +67 -0
  321. agentcore/cli/external_requirements/checks.py +280 -0
  322. agentcore/cli/external_requirements/detect.py +55 -0
  323. agentcore/cli/external_requirements/versions.py +57 -0
  324. agentcore/cli/groups.py +23 -0
  325. agentcore/cli/interactive.py +85 -0
  326. agentcore/cli/main.py +137 -0
  327. agentcore/cli/naming.py +11 -0
  328. agentcore/cli/notices.py +42 -0
  329. agentcore/cli/project.py +34 -0
  330. agentcore/cli/run_command.py +27 -0
  331. agentcore/cli/tree.py +135 -0
  332. agentcore/cli/update_notifier.py +123 -0
  333. agentcore/cli/variadic.py +50 -0
  334. agentcore/cloudformation/__init__.py +84 -0
  335. agentcore/cloudformation/bootstrap.py +64 -0
  336. agentcore/cloudformation/logical_ids.py +37 -0
  337. agentcore/cloudformation/outputs.py +566 -0
  338. agentcore/cloudformation/stack_discovery.py +75 -0
  339. agentcore/cloudformation/stack_events.py +107 -0
  340. agentcore/cloudformation/stack_status.py +98 -0
  341. agentcore/cloudformation/types.py +44 -0
  342. agentcore/lib/__init__.py +68 -0
  343. agentcore/lib/constants.py +77 -0
  344. agentcore/lib/dependency_management/__init__.py +23 -0
  345. agentcore/lib/dependency_management/messages.py +92 -0
  346. agentcore/lib/dependency_management/plan.py +98 -0
  347. agentcore/lib/dependency_management/semver.py +137 -0
  348. agentcore/lib/dependency_management/sync.py +139 -0
  349. agentcore/lib/dependency_management/types.py +56 -0
  350. agentcore/lib/errors/__init__.py +5 -0
  351. agentcore/lib/errors/types.py +352 -0
  352. agentcore/lib/errors/validation.py +121 -0
  353. agentcore/lib/packaging/__init__.py +81 -0
  354. agentcore/lib/packaging/build_args.py +23 -0
  355. agentcore/lib/packaging/build_context.py +26 -0
  356. agentcore/lib/packaging/build_context_dockerignore.py +45 -0
  357. agentcore/lib/packaging/container.py +95 -0
  358. agentcore/lib/packaging/helpers.py +289 -0
  359. agentcore/lib/packaging/node.py +153 -0
  360. agentcore/lib/packaging/python.py +135 -0
  361. agentcore/lib/packaging/types.py +69 -0
  362. agentcore/lib/packaging/uv.py +45 -0
  363. agentcore/lib/result.py +104 -0
  364. agentcore/lib/schemas/__init__.py +1 -0
  365. agentcore/lib/schemas/io/__init__.py +27 -0
  366. agentcore/lib/schemas/io/config_io.py +458 -0
  367. agentcore/lib/schemas/io/global_config.py +239 -0
  368. agentcore/lib/schemas/io/path_resolver.py +132 -0
  369. agentcore/lib/secrets/__init__.py +18 -0
  370. agentcore/lib/secrets/cipher.py +70 -0
  371. agentcore/lib/secrets/key_provider.py +163 -0
  372. agentcore/lib/secrets/sensitive_keys.py +55 -0
  373. agentcore/lib/time_constants.py +4 -0
  374. agentcore/lib/utils/__init__.py +47 -0
  375. agentcore/lib/utils/aws_account.py +15 -0
  376. agentcore/lib/utils/credentials.py +68 -0
  377. agentcore/lib/utils/dotenv.py +32 -0
  378. agentcore/lib/utils/env.py +105 -0
  379. agentcore/lib/utils/json_format.py +29 -0
  380. agentcore/lib/utils/json_rpc.py +22 -0
  381. agentcore/lib/utils/platform.py +33 -0
  382. agentcore/lib/utils/polling.py +86 -0
  383. agentcore/lib/utils/subprocess.py +135 -0
  384. agentcore/lib/utils/time_parser.py +48 -0
  385. agentcore/lib/utils/validation.py +106 -0
  386. agentcore/logging/__init__.py +10 -0
  387. agentcore/logging/_common.py +77 -0
  388. agentcore/logging/cdk_io_host.py +36 -0
  389. agentcore/logging/create_logger.py +107 -0
  390. agentcore/logging/dev_logger.py +63 -0
  391. agentcore/logging/exec_logger.py +159 -0
  392. agentcore/logging/invoke_logger.py +154 -0
  393. agentcore/logging/remove_logger.py +95 -0
  394. agentcore/operations/__init__.py +0 -0
  395. agentcore/operations/agent/__init__.py +0 -0
  396. agentcore/operations/agent/config_bundle_defaults.py +31 -0
  397. agentcore/operations/agent/generate/__init__.py +28 -0
  398. agentcore/operations/agent/generate/schema_mapper.py +319 -0
  399. agentcore/operations/agent/generate/types.py +172 -0
  400. agentcore/operations/agent/generate/write_agent_to_project.py +67 -0
  401. agentcore/operations/agent/import_/__init__.py +31 -0
  402. agentcore/operations/agent/import_/base_translator.py +449 -0
  403. agentcore/operations/agent/import_/constants.py +23 -0
  404. agentcore/operations/agent/import_/execute.py +127 -0
  405. agentcore/operations/agent/import_/langgraph_translator.py +294 -0
  406. agentcore/operations/agent/import_/pyproject_generator.py +73 -0
  407. agentcore/operations/agent/import_/strands_translator.py +289 -0
  408. agentcore/operations/config_bundle/__init__.py +1 -0
  409. agentcore/operations/config_bundle/bundle_name_variants.py +9 -0
  410. agentcore/operations/config_bundle/diff_versions.py +52 -0
  411. agentcore/operations/config_bundle/resolve_bundle.py +65 -0
  412. agentcore/operations/connectors/__init__.py +3 -0
  413. agentcore/operations/connectors/translators.py +63 -0
  414. agentcore/operations/dataset/__init__.py +21 -0
  415. agentcore/operations/dataset/delete.py +7 -0
  416. agentcore/operations/dataset/publish.py +16 -0
  417. agentcore/operations/dataset/pull.py +21 -0
  418. agentcore/operations/dataset/push.py +201 -0
  419. agentcore/operations/dataset/resolve_dataset.py +65 -0
  420. agentcore/operations/dataset/status.py +18 -0
  421. agentcore/operations/dataset/wait.py +25 -0
  422. agentcore/operations/deploy/__init__.py +152 -0
  423. agentcore/operations/deploy/backfill_vpc_id.py +90 -0
  424. agentcore/operations/deploy/change_detection.py +84 -0
  425. agentcore/operations/deploy/constants.py +58 -0
  426. agentcore/operations/deploy/dependency_sync.py +105 -0
  427. agentcore/operations/deploy/ensure_target.py +30 -0
  428. agentcore/operations/deploy/gateway_status.py +44 -0
  429. agentcore/operations/deploy/managed_memory_notice.py +36 -0
  430. agentcore/operations/deploy/payment_connector_authorization.py +106 -0
  431. agentcore/operations/deploy/post_deploy_datasets.py +96 -0
  432. agentcore/operations/deploy/post_deploy_knowledge_bases.py +104 -0
  433. agentcore/operations/deploy/post_deploy_observability.py +28 -0
  434. agentcore/operations/deploy/post_deploy_online_evals.py +60 -0
  435. agentcore/operations/deploy/pre_deploy_identity.py +505 -0
  436. agentcore/operations/deploy/preflight.py +385 -0
  437. agentcore/operations/deploy/region_override.py +45 -0
  438. agentcore/operations/deploy/teardown.py +153 -0
  439. agentcore/operations/dev/__init__.py +61 -0
  440. agentcore/operations/dev/_http.py +79 -0
  441. agentcore/operations/dev/_server.py +165 -0
  442. agentcore/operations/dev/codezip_dev_server.py +151 -0
  443. agentcore/operations/dev/config.py +128 -0
  444. agentcore/operations/dev/constants.py +9 -0
  445. agentcore/operations/dev/container_dev_server.py +237 -0
  446. agentcore/operations/dev/container_runtime.py +37 -0
  447. agentcore/operations/dev/dev_server.py +244 -0
  448. agentcore/operations/dev/gateway_env.py +25 -0
  449. agentcore/operations/dev/invoke.py +214 -0
  450. agentcore/operations/dev/invoke_a2a.py +204 -0
  451. agentcore/operations/dev/invoke_agui.py +88 -0
  452. agentcore/operations/dev/invoke_mcp.py +145 -0
  453. agentcore/operations/dev/invoke_types.py +30 -0
  454. agentcore/operations/dev/load_dev_env.py +26 -0
  455. agentcore/operations/dev/memory_env.py +19 -0
  456. agentcore/operations/dev/otel/__init__.py +5 -0
  457. agentcore/operations/dev/otel/collector.py +234 -0
  458. agentcore/operations/dev/otel/transforms.py +331 -0
  459. agentcore/operations/dev/payment_env.py +50 -0
  460. agentcore/operations/dev/server.py +28 -0
  461. agentcore/operations/dev/sse_transform.py +30 -0
  462. agentcore/operations/dev/utils.py +152 -0
  463. agentcore/operations/dev/web_ui/__init__.py +31 -0
  464. agentcore/operations/dev/web_ui/constants.py +25 -0
  465. agentcore/operations/dev/web_ui/handlers/__init__.py +36 -0
  466. agentcore/operations/dev/web_ui/handlers/_common.py +36 -0
  467. agentcore/operations/dev/web_ui/handlers/_deployed.py +37 -0
  468. agentcore/operations/dev/web_ui/handlers/a2a_proxy.py +37 -0
  469. agentcore/operations/dev/web_ui/handlers/cloudwatch_traces.py +71 -0
  470. agentcore/operations/dev/web_ui/handlers/harness_invocation.py +89 -0
  471. agentcore/operations/dev/web_ui/handlers/harness_utils.py +95 -0
  472. agentcore/operations/dev/web_ui/handlers/invocations.py +327 -0
  473. agentcore/operations/dev/web_ui/handlers/mcp_proxy.py +119 -0
  474. agentcore/operations/dev/web_ui/handlers/memory.py +84 -0
  475. agentcore/operations/dev/web_ui/handlers/resources.py +351 -0
  476. agentcore/operations/dev/web_ui/handlers/start.py +182 -0
  477. agentcore/operations/dev/web_ui/handlers/status.py +25 -0
  478. agentcore/operations/dev/web_ui/handlers/traces.py +50 -0
  479. agentcore/operations/dev/web_ui/run_web_ui.py +60 -0
  480. agentcore/operations/dev/web_ui/web_server.py +297 -0
  481. agentcore/operations/eval/__init__.py +8 -0
  482. agentcore/operations/eval/list_eval_runs.py +18 -0
  483. agentcore/operations/eval/logs_eval.py +119 -0
  484. agentcore/operations/eval/pause_resume.py +90 -0
  485. agentcore/operations/eval/run_eval.py +354 -0
  486. agentcore/operations/eval/shared/__init__.py +0 -0
  487. agentcore/operations/eval/shared/dataset_loader.py +68 -0
  488. agentcore/operations/eval/shared/dataset_session_provider.py +122 -0
  489. agentcore/operations/eval/shared/evaluator_runner.py +89 -0
  490. agentcore/operations/eval/shared/scenario_executor.py +71 -0
  491. agentcore/operations/eval/shared/span_collector.py +255 -0
  492. agentcore/operations/eval/storage.py +67 -0
  493. agentcore/operations/feedback/__init__.py +21 -0
  494. agentcore/operations/feedback/aperture_client.py +98 -0
  495. agentcore/operations/feedback/build_payload.py +97 -0
  496. agentcore/operations/feedback/constants.py +26 -0
  497. agentcore/operations/feedback/submit_feedback.py +150 -0
  498. agentcore/operations/fetch_access/__init__.py +36 -0
  499. agentcore/operations/fetch_access/_target.py +17 -0
  500. agentcore/operations/fetch_access/fetch_gateway_token.py +75 -0
  501. agentcore/operations/fetch_access/fetch_harness_token.py +72 -0
  502. agentcore/operations/fetch_access/fetch_runtime_token.py +76 -0
  503. agentcore/operations/fetch_access/list_agents.py +18 -0
  504. agentcore/operations/fetch_access/list_gateways.py +26 -0
  505. agentcore/operations/fetch_access/list_harnesses.py +23 -0
  506. agentcore/operations/fetch_access/oauth_token.py +162 -0
  507. agentcore/operations/fetch_access/types.py +34 -0
  508. agentcore/operations/harness/__init__.py +1 -0
  509. agentcore/operations/harness/orphan.py +84 -0
  510. agentcore/operations/harness/skill_utils.py +56 -0
  511. agentcore/operations/identity/__init__.py +33 -0
  512. agentcore/operations/identity/api_key_credential_provider.py +68 -0
  513. agentcore/operations/identity/oauth2_credential_provider.py +95 -0
  514. agentcore/operations/ingest/__init__.py +184 -0
  515. agentcore/operations/init/__init__.py +3 -0
  516. agentcore/operations/init/files.py +59 -0
  517. agentcore/operations/insights/__init__.py +21 -0
  518. agentcore/operations/insights/insights_storage.py +67 -0
  519. agentcore/operations/insights/run_insights.py +148 -0
  520. agentcore/operations/invoke/__init__.py +5 -0
  521. agentcore/operations/invoke/resolve_agent_context.py +85 -0
  522. agentcore/operations/jobs/__init__.py +38 -0
  523. agentcore/operations/jobs/ab_test/__init__.py +0 -0
  524. agentcore/operations/jobs/ab_test/build_options.py +126 -0
  525. agentcore/operations/jobs/ab_test/format.py +121 -0
  526. agentcore/operations/jobs/ab_test/handler.py +412 -0
  527. agentcore/operations/jobs/ab_test/promote.py +142 -0
  528. agentcore/operations/jobs/ab_test/resolve.py +221 -0
  529. agentcore/operations/jobs/batch_evaluation/__init__.py +0 -0
  530. agentcore/operations/jobs/batch_evaluation/build_source.py +68 -0
  531. agentcore/operations/jobs/batch_evaluation/dataset_phase1.py +95 -0
  532. agentcore/operations/jobs/batch_evaluation/format.py +58 -0
  533. agentcore/operations/jobs/batch_evaluation/handler.py +203 -0
  534. agentcore/operations/jobs/insights/__init__.py +0 -0
  535. agentcore/operations/jobs/insights/format.py +65 -0
  536. agentcore/operations/jobs/insights/handler.py +178 -0
  537. agentcore/operations/jobs/recommendation/__init__.py +0 -0
  538. agentcore/operations/jobs/recommendation/apply_to_bundle.py +76 -0
  539. agentcore/operations/jobs/recommendation/build_config.py +271 -0
  540. agentcore/operations/jobs/recommendation/fetch_session_spans.py +93 -0
  541. agentcore/operations/jobs/recommendation/format.py +77 -0
  542. agentcore/operations/jobs/recommendation/handler.py +331 -0
  543. agentcore/operations/jobs/shared/__init__.py +0 -0
  544. agentcore/operations/jobs/shared/constants.py +85 -0
  545. agentcore/operations/jobs/shared/engine.py +187 -0
  546. agentcore/operations/jobs/shared/format.py +104 -0
  547. agentcore/operations/jobs/shared/region.py +34 -0
  548. agentcore/operations/jobs/shared/resolve_agent_state.py +30 -0
  549. agentcore/operations/jobs/shared/storage.py +117 -0
  550. agentcore/operations/jobs/shared/wait.py +30 -0
  551. agentcore/operations/knowledge_base/__init__.py +33 -0
  552. agentcore/operations/knowledge_base/connector_config.py +105 -0
  553. agentcore/operations/knowledge_base/hydrate_data_sources.py +59 -0
  554. agentcore/operations/mcp/__init__.py +4 -0
  555. agentcore/operations/memory/__init__.py +13 -0
  556. agentcore/operations/memory/_records.py +72 -0
  557. agentcore/operations/memory/list_memory_records.py +45 -0
  558. agentcore/operations/memory/retrieve_memory_records.py +52 -0
  559. agentcore/operations/node/__init__.py +15 -0
  560. agentcore/operations/node/setup.py +36 -0
  561. agentcore/operations/python/__init__.py +17 -0
  562. agentcore/operations/python/setup.py +47 -0
  563. agentcore/operations/resolve_agent.py +159 -0
  564. agentcore/operations/session/__init__.py +86 -0
  565. agentcore/operations/traces/__init__.py +29 -0
  566. agentcore/operations/traces/get_trace.py +202 -0
  567. agentcore/operations/traces/insights_query.py +74 -0
  568. agentcore/operations/traces/list_traces.py +46 -0
  569. agentcore/operations/traces/trace_url.py +25 -0
  570. agentcore/operations/traces/types.py +55 -0
  571. agentcore/primitives/__init__.py +0 -0
  572. agentcore/primitives/_gateway_target_wizard.py +293 -0
  573. agentcore/primitives/_gateway_validation.py +442 -0
  574. agentcore/primitives/_harness_cli.py +557 -0
  575. agentcore/primitives/_harness_validation.py +163 -0
  576. agentcore/primitives/_harness_wizard.py +726 -0
  577. agentcore/primitives/_knowledge_base_wizard.py +259 -0
  578. agentcore/primitives/_payment_wizard.py +331 -0
  579. agentcore/primitives/_policy_form.py +160 -0
  580. agentcore/primitives/agent.py +817 -0
  581. agentcore/primitives/auth_utils.py +77 -0
  582. agentcore/primitives/base.py +178 -0
  583. agentcore/primitives/capacity_provider.py +501 -0
  584. agentcore/primitives/config_bundle.py +329 -0
  585. agentcore/primitives/credential.py +387 -0
  586. agentcore/primitives/credential_utils.py +45 -0
  587. agentcore/primitives/dataset.py +211 -0
  588. agentcore/primitives/deployed_gateways.py +34 -0
  589. agentcore/primitives/evaluator.py +909 -0
  590. agentcore/primitives/gateway.py +496 -0
  591. agentcore/primitives/gateway_target.py +988 -0
  592. agentcore/primitives/harness.py +706 -0
  593. agentcore/primitives/knowledge_base.py +477 -0
  594. agentcore/primitives/memory.py +387 -0
  595. agentcore/primitives/online_eval_config.py +365 -0
  596. agentcore/primitives/online_insights.py +275 -0
  597. agentcore/primitives/payment_connector.py +427 -0
  598. agentcore/primitives/payment_eligible.py +20 -0
  599. agentcore/primitives/payment_manager.py +605 -0
  600. agentcore/primitives/payment_validation.py +68 -0
  601. agentcore/primitives/policy.py +622 -0
  602. agentcore/primitives/policy_engine.py +358 -0
  603. agentcore/primitives/registry.py +56 -0
  604. agentcore/primitives/runtime_endpoint.py +361 -0
  605. agentcore/primitives/secret_flag_warning.py +17 -0
  606. agentcore/schema/__init__.py +14 -0
  607. agentcore/schema/_zod.py +395 -0
  608. agentcore/schema/constants.py +306 -0
  609. agentcore/schema/schemas/__init__.py +40 -0
  610. agentcore/schema/schemas/agent_env.py +545 -0
  611. agentcore/schema/schemas/agentcore_project.py +530 -0
  612. agentcore/schema/schemas/auth.py +286 -0
  613. agentcore/schema/schemas/aws_targets.py +72 -0
  614. agentcore/schema/schemas/connections.py +187 -0
  615. agentcore/schema/schemas/deployed_state.py +322 -0
  616. agentcore/schema/schemas/mcp.py +650 -0
  617. agentcore/schema/schemas/mcp_defs.py +54 -0
  618. agentcore/schema/schemas/primitives/__init__.py +52 -0
  619. agentcore/schema/schemas/primitives/ab_test.py +162 -0
  620. agentcore/schema/schemas/primitives/capacity_provider.py +214 -0
  621. agentcore/schema/schemas/primitives/config_bundle.py +48 -0
  622. agentcore/schema/schemas/primitives/dataset.py +55 -0
  623. agentcore/schema/schemas/primitives/evaluator.py +171 -0
  624. agentcore/schema/schemas/primitives/harness.py +710 -0
  625. agentcore/schema/schemas/primitives/knowledge_base.py +90 -0
  626. agentcore/schema/schemas/primitives/memory.py +113 -0
  627. agentcore/schema/schemas/primitives/online_eval_config.py +77 -0
  628. agentcore/schema/schemas/primitives/payment.py +114 -0
  629. agentcore/schema/schemas/primitives/policy.py +83 -0
  630. agentcore/schema/schemas/primitives/tags.py +50 -0
  631. agentcore/schema/schemas/zod_util.py +5 -0
  632. agentcore/schema/types/__init__.py +3 -0
  633. agentcore/schema/types/path.py +16 -0
  634. agentcore/templates/__init__.py +115 -0
  635. agentcore/templates/_handlebars.py +782 -0
  636. agentcore/templates/_js.py +164 -0
  637. agentcore/templates/base_renderer.py +107 -0
  638. agentcore/templates/cdk_renderer.py +129 -0
  639. agentcore/templates/evaluator_renderer.py +39 -0
  640. agentcore/templates/gateway_target_renderer.py +69 -0
  641. agentcore/templates/llm_context/README.md +16 -0
  642. agentcore/templates/llm_context/agentcore.ts +685 -0
  643. agentcore/templates/llm_context/aws-targets.ts +51 -0
  644. agentcore/templates/profiles.py +151 -0
  645. agentcore/templates/render.py +92 -0
  646. agentcore/templates/renderers.py +83 -0
  647. agentcore/templates/schema_assets.py +23 -0
  648. agentcore/templates/template_root.py +28 -0
  649. agentcore/templates/types.py +192 -0
  650. agentcore_cli-0.31.1.dist-info/METADATA +84 -0
  651. agentcore_cli-0.31.1.dist-info/RECORD +655 -0
  652. agentcore_cli-0.31.1.dist-info/WHEEL +4 -0
  653. agentcore_cli-0.31.1.dist-info/entry_points.txt +2 -0
  654. agentcore_cli-0.31.1.dist-info/licenses/LICENSE +175 -0
  655. agentcore_cli-0.31.1.dist-info/licenses/NOTICE +88 -0
@@ -0,0 +1,412 @@
1
+ """AB-test job handler (port of operations/jobs/ab-test/handler.ts).
2
+
3
+ - create(): resolve region + gateway ARN, build variants + eval config, create (or reuse) the
4
+ execution role, ONE CreateABTest (AccessDenied retry while IAM propagates).
5
+ - refresh(): GET latest state (404 -> NOT_FOUND).
6
+ - stop/pause/resume(): UpdateABTest executionStatus = STOPPED / PAUSED / RUNNING.
7
+ - promote(): dry-run validation, wait until RUNNING, stop, apply the winning variant.
8
+ - archive(): stop -> poll STOPPED -> DeleteABTest -> delete the role if the CLI created it.
9
+ """
10
+
11
+ import time
12
+ from collections.abc import Callable
13
+ from typing import Any
14
+
15
+ from agentcore.aws import agentcore_ab_tests as api
16
+ from agentcore.aws import agentcore_control as control
17
+ from agentcore.aws._aws_errors import aws_error_name, aws_http_status
18
+ from agentcore.aws.account import create_aws_client
19
+ from agentcore.cli.errors import get_error_message
20
+ from agentcore.lib import ConfigIO, JobNotFoundError, ResourceNotFoundError
21
+ from agentcore.lib.errors.types import to_error
22
+ from agentcore.lib.result import Err, Ok
23
+ from agentcore.lib.schemas.io.config_io import to_jsonable
24
+ from agentcore.lib.utils.json_format import to_json_string
25
+ from agentcore.operations.jobs.ab_test import promote as _promote
26
+ from agentcore.operations.jobs.ab_test import resolve as _resolve
27
+ from agentcore.operations.jobs.ab_test.build_options import build_ab_test_request
28
+ from agentcore.operations.jobs.batch_evaluation.handler import new_logger
29
+ from agentcore.operations.jobs.shared.constants import NOT_FOUND_STATUS
30
+ from agentcore.operations.jobs.shared.format import iso_now
31
+ from agentcore.operations.jobs.shared.region import region_of, resolve_job_region
32
+ from agentcore.operations.jobs.shared.resolve_agent_state import deployed_dict
33
+ from agentcore.operations.jobs.shared.storage import drop_undefined
34
+
35
+ MAX_CREATE_RETRIES = 5
36
+ BASE_RETRY_DELAY_MS = 5_000
37
+
38
+ # Injectable for tests.
39
+ sleep: Callable[[float], None] = time.sleep
40
+
41
+
42
+ def merge_deployed_resources(deployed_state: dict[str, Any]) -> dict[str, Any]:
43
+ """Merge per-target deployed resources (AB tests resolve names across all targets)."""
44
+ merged: dict[str, Any] = {}
45
+ for target in (deployed_state.get("targets") or {}).values():
46
+ r = (target or {}).get("resources")
47
+ if not r:
48
+ continue
49
+ merged["mcp"] = {**(merged.get("mcp") or {}), **(r.get("mcp") or {})}
50
+ for key in ("gateways", "configBundles", "onlineEvalConfigs"):
51
+ merged[key] = {**(merged.get(key) or {}), **(r.get(key) or {})}
52
+ return merged
53
+
54
+
55
+ def _poll_until_stopped(region: str, ab_test_id: str, attempts: int = 20, delay_ms: int = 3_000) -> bool:
56
+ for _ in range(attempts):
57
+ try:
58
+ if api.get_ab_test(region=region, ab_test_id=ab_test_id).get("executionStatus") == "STOPPED":
59
+ return True
60
+ except JobNotFoundError:
61
+ return True
62
+ except Exception: # noqa: BLE001, S110 - transient: keep polling
63
+ pass
64
+ sleep(delay_ms / 1000)
65
+ return False
66
+
67
+
68
+ def _wait_for_running_then_stop(region: str, ab_test_id: str, attempts: int = 12, delay_ms: int = 10_000) -> None:
69
+ status = None
70
+ for _ in range(attempts):
71
+ status = api.get_ab_test(region=region, ab_test_id=ab_test_id).get("executionStatus")
72
+ if status == "RUNNING":
73
+ break
74
+ if status == "STOPPED":
75
+ return
76
+ sleep(delay_ms / 1000)
77
+ if status != "RUNNING":
78
+ raise Exception(f'A/B test "{ab_test_id}" did not reach RUNNING (current: {status}); cannot promote.')
79
+ api.update_ab_test(region=region, ab_test_id=ab_test_id, execution_status="STOPPED")
80
+
81
+
82
+ def _is_retryable_create_error(exc: BaseException) -> bool:
83
+ message = str(exc)
84
+ return (
85
+ aws_error_name(exc) == "AccessDeniedException"
86
+ or aws_http_status(exc) == 403
87
+ or "Access denied" in message
88
+ or "Gateway validation error" in message
89
+ )
90
+
91
+
92
+ def create(opts: dict[str, Any], config_io: ConfigIO) -> Ok | Err:
93
+ logger = new_logger("ab-test")
94
+ region = ""
95
+ role_arn: str | None = None
96
+ role_created_by_cli = False
97
+ on_progress = opts.get("onProgress") or (lambda _s, _m: None)
98
+ try:
99
+ if logger:
100
+ logger.start_step("Load project config")
101
+ project = to_jsonable(config_io.read_project_spec())
102
+ deployed_state = deployed_dict(config_io.read_deployed_state())
103
+ aws_targets = config_io.resolve_aws_deployment_targets()
104
+ region = resolve_job_region(opts.get("region"), aws_targets)
105
+ deployed = merge_deployed_resources(deployed_state)
106
+ if logger:
107
+ logger.end_step("success")
108
+ logger.start_step("Resolve gateway")
109
+ gateway_arn = _resolve.resolve_gateway_arn(opts["gateway"], deployed)
110
+ if not gateway_arn or not gateway_arn.startswith("arn:") or len(gateway_arn.split(":")) < 6:
111
+ err = ResourceNotFoundError(
112
+ f'Gateway "{opts["gateway"]}" is not deployed. Run `agentcore add gateway` and `agentcore deploy` first.'
113
+ )
114
+ if logger:
115
+ logger.end_step("error", err.message)
116
+ logger.finalize(False)
117
+ return Err(err)
118
+ if logger:
119
+ logger.log(f"Gateway ARN: {gateway_arn}")
120
+ logger.end_step("success")
121
+
122
+ built = build_ab_test_request(opts, deployed)
123
+
124
+ if logger:
125
+ logger.start_step("Resolve execution role")
126
+ if opts.get("roleArn"):
127
+ role_arn = opts["roleArn"]
128
+ else:
129
+ on_progress("role", "Creating execution role (waiting for IAM propagation)...")
130
+ role_arn = _resolve.get_or_create_ab_test_role(
131
+ region=region, project_name=project["name"], test_name=opts["name"], gateway_arn=gateway_arn
132
+ )
133
+ role_created_by_cli = True
134
+ if logger:
135
+ logger.log(f"Role ARN: {role_arn}")
136
+ logger.end_step("success")
137
+ logger.start_step("Create A/B test")
138
+ on_progress("starting", f'Creating A/B test "{opts["name"]}"...')
139
+
140
+ created = None
141
+ for attempt in range(MAX_CREATE_RETRIES):
142
+ try:
143
+ created = api.create_ab_test(
144
+ region=region,
145
+ name=f"{project['name']}_{opts['name']}",
146
+ description=opts.get("description"),
147
+ gateway_arn=gateway_arn,
148
+ role_arn=role_arn, # type: ignore[arg-type]
149
+ variants=built["variants"],
150
+ evaluation_config=built["evaluationConfig"],
151
+ gateway_filter=built["gatewayFilter"],
152
+ enable_on_create=opts.get("enableOnCreate"),
153
+ )
154
+ break
155
+ except Exception as exc:
156
+ if _is_retryable_create_error(exc) and attempt < MAX_CREATE_RETRIES - 1:
157
+ on_progress("retry", f"Access not yet propagated; retrying (attempt {attempt + 2})...")
158
+ sleep(BASE_RETRY_DELAY_MS * (2**attempt) / 1000)
159
+ continue
160
+ raise
161
+ if not created:
162
+ raise Exception("A/B test creation failed after retries.")
163
+ if logger:
164
+ logger.log(f"Response: {to_json_string(created)}")
165
+ logger.end_step("success")
166
+ on_progress("started", f"A/B test created: {created['abTestId']} ({created['executionStatus']})")
167
+ if logger:
168
+ logger.finalize(True)
169
+
170
+ target_names = (
171
+ []
172
+ if opts["mode"] == "target-based"
173
+ else _resolve.resolve_runtime_target_names(
174
+ opts["gateway"], opts.get("runtime") or opts.get("agent"), project
175
+ )
176
+ )
177
+ record = {
178
+ "type": "ab-test",
179
+ "id": created["abTestId"],
180
+ "arn": created["abTestArn"],
181
+ "status": created["status"],
182
+ "lifecycleStatus": created["executionStatus"],
183
+ "createdAt": created.get("createdAt") or iso_now(),
184
+ "agent": opts.get("agent") or opts.get("runtime") or opts["name"],
185
+ "logFilePath": logger.log_file_path if logger else None,
186
+ "name": opts["name"],
187
+ "mode": opts["mode"],
188
+ "gatewayArn": gateway_arn,
189
+ "gatewayName": opts["gateway"],
190
+ "targetName": target_names[0] if len(target_names) == 1 else None,
191
+ "targetCandidates": target_names if len(target_names) > 1 else None,
192
+ "roleArn": role_arn,
193
+ "roleCreatedByCli": role_created_by_cli,
194
+ "variants": built["variantSummaries"],
195
+ "evaluationConfig": built["evaluationConfig"],
196
+ "gatewayFilter": built["gatewayFilter"],
197
+ }
198
+ return Ok(drop_undefined(record))
199
+ except Exception as exc: # noqa: BLE001
200
+ if role_created_by_cli and role_arn and region:
201
+ try:
202
+ _resolve.delete_ab_test_role(region, role_arn)
203
+ except Exception: # noqa: BLE001, S110
204
+ pass
205
+ if logger:
206
+ logger.finalize(False)
207
+ return Err(to_error(exc))
208
+
209
+
210
+ def refresh(record: dict[str, Any]) -> Ok | Err:
211
+ try:
212
+ response = api.get_ab_test(region=region_of(record["arn"]), ab_test_id=record["id"])
213
+ except JobNotFoundError:
214
+ return Ok({**record, "status": NOT_FOUND_STATUS, "lifecycleStatus": NOT_FOUND_STATUS})
215
+ except Exception as exc: # noqa: BLE001
216
+ return Err(to_error(exc))
217
+ failure = response.get("failureReason")
218
+ if failure is None and response.get("errorDetails") is not None:
219
+ failure = "; ".join(response["errorDetails"])
220
+ if failure is None:
221
+ failure = record.get("failureReason")
222
+ updated = {
223
+ **record,
224
+ "status": response.get("status"),
225
+ "lifecycleStatus": response.get("executionStatus"),
226
+ "completedAt": response.get("stoppedAt") or record.get("completedAt"),
227
+ "maxDurationExpiresAt": response.get("maxDurationExpiresAt") or record.get("maxDurationExpiresAt"),
228
+ "results": response.get("results") or record.get("results"),
229
+ "failureReason": failure,
230
+ }
231
+ return Ok(drop_undefined(updated))
232
+
233
+
234
+ def _set_execution(record: dict[str, Any], status: str) -> None:
235
+ api.update_ab_test(region=region_of(record["arn"]), ab_test_id=record["id"], execution_status=status) # type: ignore[arg-type]
236
+
237
+
238
+ def stop(record: dict[str, Any]) -> Ok | Err:
239
+ try:
240
+ _set_execution(record, "STOPPED")
241
+ return Ok(None)
242
+ except Exception as exc: # noqa: BLE001
243
+ return Err(to_error(exc))
244
+
245
+
246
+ def pause(record: dict[str, Any]) -> Ok | Err:
247
+ try:
248
+ _set_execution(record, "PAUSED")
249
+ return Ok({**record, "lifecycleStatus": "PAUSED"})
250
+ except Exception as exc: # noqa: BLE001
251
+ return Err(to_error(exc))
252
+
253
+
254
+ def resume(record: dict[str, Any]) -> Ok | Err:
255
+ try:
256
+ _set_execution(record, "RUNNING")
257
+ return Ok({**record, "lifecycleStatus": "RUNNING"})
258
+ except Exception as exc: # noqa: BLE001
259
+ return Err(to_error(exc))
260
+
261
+
262
+ def promote(record: dict[str, Any], config_io: ConfigIO | None = None) -> Ok | Err:
263
+ region = region_of(record["arn"])
264
+ try:
265
+ preflight = _promote.promote_ab_test_config(record, True)
266
+ if not preflight["promoted"]:
267
+ return Err(
268
+ Exception(
269
+ f'Cannot promote A/B test "{record["id"]}": {preflight["promotionDetail"]} '
270
+ "The test was left running (not stopped)."
271
+ )
272
+ )
273
+ _wait_for_running_then_stop(region, record["id"])
274
+ promotion = _promote.promote_ab_test_config(record)
275
+ if not promotion["promoted"]:
276
+ return Err(
277
+ Exception(
278
+ f'A/B test "{record["id"]}" was stopped, but the winning variant could not be applied to '
279
+ f"agentcore.json: {promotion['promotionDetail']}"
280
+ )
281
+ )
282
+ return Ok({**record, "lifecycleStatus": "STOPPED"})
283
+ except Exception as exc: # noqa: BLE001
284
+ return Err(to_error(exc))
285
+
286
+
287
+ def archive(record: dict[str, Any]) -> Ok | Err:
288
+ region = region_of(record["arn"])
289
+ try:
290
+ try:
291
+ _set_execution(record, "STOPPED")
292
+ _poll_until_stopped(region, record["id"])
293
+ except Exception: # noqa: BLE001, S110 - already stopped / transient: proceed to delete
294
+ pass
295
+ deleted = api.delete_ab_test(region=region, ab_test_id=record["id"])
296
+ if not deleted.get("success") and "404" not in (deleted.get("error") or ""):
297
+ return Err(Exception(deleted.get("error") or "Failed to delete A/B test."))
298
+ if record.get("roleCreatedByCli") and record.get("roleArn"):
299
+ try:
300
+ all_tests = api.list_ab_tests(region=region, max_results=100)
301
+ active = [
302
+ t
303
+ for t in all_tests["abTests"]
304
+ if t.get("abTestId") != record["id"]
305
+ and t.get("status") not in ("STOPPED", "CREATE_FAILED", "DELETE_FAILED")
306
+ ]
307
+ in_use = any(
308
+ api.get_ab_test(region=region, ab_test_id=t["abTestId"]).get("roleArn") == record["roleArn"]
309
+ for t in active
310
+ )
311
+ if not in_use:
312
+ _resolve.delete_ab_test_role(region, record["roleArn"])
313
+ except Exception: # noqa: BLE001, S110 - can't verify: keep the role
314
+ pass
315
+ return Ok(None)
316
+ except JobNotFoundError:
317
+ return Ok(None)
318
+ except Exception as exc: # noqa: BLE001
319
+ return Err(to_error(exc))
320
+
321
+
322
+ def debug(record: dict[str, Any]) -> Ok | Err:
323
+ region = region_of(record["arn"])
324
+ checks: list[dict[str, str]] = []
325
+ try:
326
+ test = api.get_ab_test(region=region, ab_test_id=record["id"])
327
+ checks.append(
328
+ {
329
+ "label": "AB Test Status",
330
+ "status": "pass"
331
+ if test.get("status") == "ACTIVE" and test.get("executionStatus") == "RUNNING"
332
+ else "warn",
333
+ "detail": f"{test.get('status')} / {test.get('executionStatus')}",
334
+ }
335
+ )
336
+ except Exception as exc: # noqa: BLE001
337
+ checks.append({"label": "AB Test Status", "status": "fail", "detail": get_error_message(exc)})
338
+ return Ok({"checks": checks})
339
+
340
+ checks.append(
341
+ {
342
+ "label": "AB Test Role",
343
+ "status": "pass" if test.get("roleArn") else "warn",
344
+ "detail": test.get("roleArn") or "No role ARN",
345
+ }
346
+ )
347
+
348
+ evaluation_config = test.get("evaluationConfig") or {}
349
+ if "perVariantOnlineEvaluationConfig" in evaluation_config:
350
+ eval_arns = [
351
+ (v.get("name", ""), v.get("onlineEvaluationConfigArn", ""))
352
+ for v in evaluation_config["perVariantOnlineEvaluationConfig"]
353
+ ]
354
+ else:
355
+ eval_arns = [("", evaluation_config.get("onlineEvaluationConfigArn", ""))]
356
+ for variant_name, eval_arn in eval_arns:
357
+ config_id = eval_arn.split("/")[-1] or eval_arn
358
+ suffix = f" ({variant_name})" if variant_name else ""
359
+ try:
360
+ config = control.get_online_evaluation_config(region=region, config_id=config_id)
361
+ checks.append(
362
+ {
363
+ "label": f"Online Eval Config{suffix}",
364
+ "status": "pass" if config.get("executionStatus") == "ENABLED" else "fail",
365
+ "detail": f"{config.get('configName')} — {config.get('executionStatus')}",
366
+ }
367
+ )
368
+ except Exception as exc: # noqa: BLE001
369
+ checks.append({"label": f"Online Eval Config{suffix}", "status": "fail", "detail": get_error_message(exc)})
370
+
371
+ gateway_id = (test.get("gatewayArn") or "").split("/")[-1]
372
+ try:
373
+ gateway = control.get_gateway_detail(region=region, gateway_id=gateway_id)
374
+ checks.append(
375
+ {
376
+ "label": "Gateway Role",
377
+ "status": "pass" if gateway.get("roleArn") else "warn",
378
+ "detail": gateway.get("roleArn") or "No role ARN",
379
+ }
380
+ )
381
+ except Exception as exc: # noqa: BLE001
382
+ checks.append({"label": "Gateway Role", "status": "fail", "detail": get_error_message(exc)})
383
+
384
+ two_hours_ago = int(time.time() * 1000) - 2 * 60 * 60 * 1000
385
+ try:
386
+ logs = create_aws_client("logs", region)
387
+ for v in test.get("variants") or []:
388
+ name = v.get("name")
389
+ try:
390
+ response = logs.filter_log_events(
391
+ logGroupName="aws/spans",
392
+ startTime=two_hours_ago,
393
+ filterPattern=f'"{test.get("abTestArn")}" "{name}"',
394
+ limit=5,
395
+ )
396
+ count = len(response.get("events") or [])
397
+ checks.append(
398
+ {
399
+ "label": f"Experiment Spans — {name} (2h)",
400
+ "status": "pass" if count > 0 else "warn",
401
+ "detail": f"{count}+ spans with experiment metadata"
402
+ if count > 0
403
+ else "No spans found — traffic may not be reaching this variant",
404
+ }
405
+ )
406
+ except Exception as exc: # noqa: BLE001
407
+ checks.append(
408
+ {"label": f"Experiment Spans — {name}", "status": "warn", "detail": get_error_message(exc)}
409
+ )
410
+ except Exception as exc: # noqa: BLE001
411
+ checks.append({"label": "Experiment Spans", "status": "warn", "detail": get_error_message(exc)})
412
+ return Ok({"checks": checks})
@@ -0,0 +1,142 @@
1
+ """Apply the winning A/B variant to agentcore.json (port of operations/jobs/ab-test/promote.ts)."""
2
+
3
+ import copy
4
+ from typing import Any
5
+
6
+ from agentcore.aws import agentcore_config_bundles as bundles_api
7
+ from agentcore.lib import ConfigIO
8
+ from agentcore.lib.schemas.io.config_io import to_jsonable
9
+ from agentcore.operations.jobs.recommendation.build_config import resolve_component_key_for_json_path
10
+ from agentcore.operations.jobs.shared.region import region_from_arn
11
+ from agentcore.operations.jobs.shared.resolve_agent_state import deployed_dict
12
+
13
+
14
+ def _bundle_id_from_arn(arn: str) -> str | None:
15
+ tail = arn.split("/")[-1]
16
+ return tail or None
17
+
18
+
19
+ def restore_placeholder_keys(
20
+ service_components: dict[str, Any], local_components: dict[str, Any] | None, deployed_state: dict[str, Any]
21
+ ) -> dict[str, Any]:
22
+ """Rewrite service ARN keys back to the bundle's portable ``{{runtime:...}}`` placeholders."""
23
+ arn_to_placeholder: dict[str, str] = {}
24
+ for key in local_components or {}:
25
+ if key.startswith("arn:"):
26
+ continue
27
+ arn = resolve_component_key_for_json_path(key, deployed_state)
28
+ if arn != key:
29
+ arn_to_placeholder[arn] = key
30
+ return {arn_to_placeholder.get(k, k): v for k, v in service_components.items()}
31
+
32
+
33
+ def _bundle_name_from_arn(deployed_state: dict[str, Any], bundle_arn: str) -> str | None:
34
+ for target in (deployed_state.get("targets") or {}).values():
35
+ for name, entry in ((((target or {}).get("resources")) or {}).get("configBundles") or {}).items():
36
+ if entry.get("bundleArn") == bundle_arn:
37
+ return name
38
+ return None
39
+
40
+
41
+ def _result(promoted: bool, mode: str | None, detail: str) -> dict[str, Any]:
42
+ return {"promoted": promoted, "mode": mode, "promotionDetail": detail}
43
+
44
+
45
+ def promote_ab_test_config(
46
+ record: dict[str, Any], dry_run: bool = False, config_io: ConfigIO | None = None
47
+ ) -> dict[str, Any]:
48
+ """{"promoted", "mode", "promotionDetail"}. ``dry_run`` validates without writing agentcore.json."""
49
+ config_io = config_io or ConfigIO()
50
+ project = to_jsonable(config_io.read_project_spec())
51
+ mode = record.get("mode")
52
+ variants = record.get("variants") or []
53
+ control = next((v for v in variants if v.get("name") == "C"), None)
54
+ treatment = next((v for v in variants if v.get("name") == "T1"), None)
55
+ if not control or not treatment:
56
+ return _result(False, mode, "A/B test record is missing control (C) or treatment (T1) variant.")
57
+
58
+ if mode == "target-based":
59
+ gateway_name = record.get("gatewayName")
60
+ if not gateway_name:
61
+ return _result(False, mode, "A/B test record is missing the gateway name; cannot locate targets.")
62
+ gateway = next((g for g in project.get("agentCoreGateways") or [] if g.get("name") == gateway_name), None)
63
+ if not gateway or gateway.get("targets") is None:
64
+ return _result(False, mode, f'Gateway "{gateway_name}" not found in agentcore.json.')
65
+ targets = gateway["targets"]
66
+ control_t = next((t for t in targets if t.get("name") == control.get("targetName")), None)
67
+ treatment_t = next((t for t in targets if t.get("name") == treatment.get("targetName")), None)
68
+ c_rt = (control_t or {}).get("httpRuntime") or {}
69
+ t_rt = (treatment_t or {}).get("httpRuntime") or {}
70
+ if not c_rt.get("runtime") or not t_rt.get("runtime"):
71
+ return _result(False, mode, "Could not resolve control/treatment runtime targets for promotion.")
72
+
73
+ c_ep, t_ep = c_rt.get("runtimeEndpoint"), t_rt.get("runtimeEndpoint")
74
+ if c_rt["runtime"] == t_rt["runtime"] and c_ep and t_ep:
75
+ runtime = next((r for r in project.get("runtimes") or [] if r.get("name") == c_rt["runtime"]), None)
76
+ endpoints = (runtime or {}).get("endpoints") or {}
77
+ control_ep, treatment_ep = endpoints.get(c_ep), endpoints.get(t_ep)
78
+ if control_ep and treatment_ep:
79
+ if not dry_run:
80
+ control_ep["version"] = treatment_ep.get("version")
81
+ config_io.write_project_spec(project)
82
+ return _result(
83
+ True,
84
+ mode,
85
+ f'Control endpoint "{c_ep}" updated to version {treatment_ep.get("version")} '
86
+ f'(from treatment "{t_ep}").',
87
+ )
88
+
89
+ if not dry_run:
90
+ control_t["httpRuntime"] = copy.deepcopy(t_rt) # type: ignore[index]
91
+ config_io.write_project_spec(project)
92
+ treatment_ref = f'{t_rt["runtime"]} (endpoint "{t_ep}")' if t_ep else t_rt["runtime"]
93
+ return _result(
94
+ True,
95
+ mode,
96
+ f'Control target "{control_t["name"]}" repointed to treatment runtime {treatment_ref}.', # type: ignore[index]
97
+ )
98
+
99
+ if not control.get("bundleArn") or not treatment.get("bundleArn"):
100
+ return _result(False, mode, "A/B test record is missing control/treatment bundle ARNs.")
101
+ if control["bundleArn"] != treatment["bundleArn"]:
102
+ return _result(
103
+ False,
104
+ mode,
105
+ "Cannot promote: control and treatment reference different config bundles. "
106
+ "A config-bundle A/B test can only promote between two versions of the SAME bundle.",
107
+ )
108
+ if not treatment.get("bundleVersion"):
109
+ return _result(False, mode, "A/B test record is missing the treatment bundle version; cannot promote.")
110
+
111
+ control_name = None
112
+ deployed_state = None
113
+ try:
114
+ deployed_state = deployed_dict(config_io.read_deployed_state())
115
+ control_name = _bundle_name_from_arn(deployed_state, control["bundleArn"])
116
+ except Exception: # noqa: BLE001, S110 - deployed state unavailable
117
+ pass
118
+ if not control_name or deployed_state is None:
119
+ return _result(
120
+ False, mode, "Could not resolve the config bundle from deployed state (deploy the bundle first)."
121
+ )
122
+ control_bundle = next((b for b in project.get("configBundles") or [] if b.get("name") == control_name), None)
123
+ if not control_bundle:
124
+ return _result(False, mode, f'Could not find config bundle "{control_name}" in agentcore.json.')
125
+ bundle_id = _bundle_id_from_arn(treatment["bundleArn"])
126
+ if not bundle_id:
127
+ return _result(False, mode, f'Could not parse bundle id from ARN "{treatment["bundleArn"]}".')
128
+
129
+ if not dry_run:
130
+ region = region_from_arn(treatment["bundleArn"]) or region_from_arn(record.get("arn", ""))
131
+ if not region:
132
+ return _result(False, mode, "Could not determine region for the config bundle.")
133
+ winning = bundles_api.get_configuration_bundle_version(
134
+ region=region, bundle_id=bundle_id, version_id=treatment["bundleVersion"]
135
+ )
136
+ control_bundle["components"] = restore_placeholder_keys(
137
+ winning.get("components") or {}, control_bundle.get("components"), deployed_state
138
+ )
139
+ config_io.write_project_spec(project)
140
+ return _result(
141
+ True, mode, f'Config bundle "{control_name}" updated to the winning version {treatment["bundleVersion"]}.'
142
+ )