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,221 @@
1
+ """AB-test resolution helpers (port of operations/jobs/ab-test/resolve.ts).
2
+
3
+ IAM role create/reuse/delete, and ARN resolution for gateway / config-bundle / online-eval
4
+ references against the merged deployed-resources dict (camelCase).
5
+ """
6
+
7
+ import hashlib
8
+ import json
9
+ import re
10
+ import time
11
+ from collections.abc import Callable
12
+ from typing import Any
13
+
14
+ from agentcore.aws._aws_errors import aws_error_name
15
+ from agentcore.aws.account import create_aws_client
16
+ from agentcore.aws.iam import validate_iam_role_trust_policy
17
+ from agentcore.aws.partition import arn_prefix
18
+
19
+ AB_TEST_ROLE_POLICY_NAME = "ABTestExecutionPolicy"
20
+
21
+ # IAM policy propagation wait after creating/updating the role (ms).
22
+ IAM_PROPAGATION_DELAY_MS = 15_000
23
+
24
+
25
+ def generate_role_name(project_name: str, test_name: str) -> str:
26
+ """AgentCore-{ProjectName}-ABTest{TestName}-{Hash} (deterministic, max 64 chars)."""
27
+ digest = hashlib.sha256(f"{project_name}:{test_name}".encode()).hexdigest()[:8]
28
+ base = f"AgentCore-{project_name}-ABTest{test_name}"
29
+ return f"{base[:55]}-{digest}"
30
+
31
+
32
+ def role_name_from_arn(role_arn: str) -> str:
33
+ return role_arn.split("/")[-1]
34
+
35
+
36
+ def _trust_policy(region: str, account_id: str) -> dict[str, Any]:
37
+ return {
38
+ "Version": "2012-10-17",
39
+ "Statement": [
40
+ {
41
+ "Effect": "Allow",
42
+ "Principal": {"Service": "bedrock-agentcore.amazonaws.com"},
43
+ "Action": "sts:AssumeRole",
44
+ "Condition": {
45
+ "StringEquals": {"aws:SourceAccount": account_id},
46
+ "ArnLike": {"aws:SourceArn": f"{arn_prefix(region)}:bedrock-agentcore:*:{account_id}:ab-test/*"},
47
+ },
48
+ }
49
+ ],
50
+ }
51
+
52
+
53
+ def _execution_policy(region: str, account_id: str) -> dict[str, Any]:
54
+ prefix = arn_prefix(region)
55
+ return {
56
+ "Version": "2012-10-17",
57
+ "Statement": [
58
+ {
59
+ "Sid": "AgentCoreResources",
60
+ "Effect": "Allow",
61
+ "Action": [
62
+ "bedrock-agentcore:GetGateway",
63
+ "bedrock-agentcore:GetGatewayTarget",
64
+ "bedrock-agentcore:ListGatewayTargets",
65
+ "bedrock-agentcore:CreateGatewayRule",
66
+ "bedrock-agentcore:UpdateGatewayRule",
67
+ "bedrock-agentcore:GetGatewayRule",
68
+ "bedrock-agentcore:DeleteGatewayRule",
69
+ "bedrock-agentcore:ListGatewayRules",
70
+ "bedrock-agentcore:GetOnlineEvaluationConfig",
71
+ "bedrock-agentcore:GetEvaluator",
72
+ "bedrock-agentcore:GetConfigurationBundle",
73
+ "bedrock-agentcore:GetConfigurationBundleVersion",
74
+ "bedrock-agentcore:ListConfigurationBundleVersions",
75
+ ],
76
+ "Resource": f"{prefix}:bedrock-agentcore:*:{account_id}:*",
77
+ "Condition": {"StringEquals": {"aws:ResourceAccount": account_id}},
78
+ },
79
+ {"Sid": "CloudWatchLogsDescribe", "Effect": "Allow", "Action": ["logs:DescribeLogGroups"], "Resource": "*"},
80
+ {
81
+ "Sid": "CloudWatchLogs",
82
+ "Effect": "Allow",
83
+ "Action": [
84
+ "logs:DescribeIndexPolicies",
85
+ "logs:PutIndexPolicy",
86
+ "logs:StartQuery",
87
+ "logs:GetQueryResults",
88
+ "logs:StopQuery",
89
+ "logs:FilterLogEvents",
90
+ "logs:GetLogEvents",
91
+ ],
92
+ "Resource": [
93
+ f"{prefix}:logs:*:{account_id}:log-group:/aws/bedrock-agentcore/evaluations/*",
94
+ f"{prefix}:logs:*:{account_id}:log-group:/aws/bedrock-agentcore/runtimes/*",
95
+ f"{prefix}:logs:*:{account_id}:log-group:aws/spans",
96
+ f"{prefix}:logs:*:{account_id}:log-group:aws/spans:*",
97
+ ],
98
+ },
99
+ ],
100
+ }
101
+
102
+
103
+ def _compact(value: Any) -> str:
104
+ return json.dumps(value, separators=(",", ":"), ensure_ascii=False)
105
+
106
+
107
+ def get_or_create_ab_test_role(
108
+ *,
109
+ region: str,
110
+ project_name: str,
111
+ test_name: str,
112
+ gateway_arn: str,
113
+ propagation_delay_ms: int | None = None,
114
+ sleep: Callable[[float], None] = time.sleep,
115
+ ) -> str:
116
+ """Create (or reuse) the AB-test execution role + inline policy, then wait for IAM propagation."""
117
+ iam = create_aws_client("iam", region)
118
+ parts = gateway_arn.split(":")
119
+ account_id = parts[4] if len(parts) > 4 else "*"
120
+ role_name = generate_role_name(project_name, test_name)
121
+ trust = _trust_policy(region, account_id)
122
+ try:
123
+ created = iam.create_role(
124
+ RoleName=role_name,
125
+ AssumeRolePolicyDocument=_compact(trust),
126
+ Description=f"Auto-created execution role for AgentCore AB test: {test_name}",
127
+ Tags=[
128
+ {"Key": "agentcore:created-by", "Value": "agentcore-cli"},
129
+ {"Key": "agentcore:project-name", "Value": project_name},
130
+ {"Key": "agentcore:ab-test-name", "Value": test_name},
131
+ ],
132
+ )
133
+ role_arn = (created.get("Role") or {}).get("Arn") or ""
134
+ if not role_arn:
135
+ raise Exception(f'IAM CreateRole succeeded but returned no role ARN for "{role_name}"')
136
+ except Exception as exc:
137
+ if aws_error_name(exc) not in ("EntityAlreadyExistsException", "EntityAlreadyExists"):
138
+ raise
139
+ existing = iam.get_role(RoleName=role_name)
140
+ role_arn = (existing.get("Role") or {}).get("Arn") or ""
141
+ if not role_arn:
142
+ raise Exception(f'Role "{role_name}" already exists but ARN could not be retrieved') from None
143
+ validate_iam_role_trust_policy(
144
+ (existing.get("Role") or {}).get("AssumeRolePolicyDocument"),
145
+ trust,
146
+ role_name,
147
+ "Delete the conflicting role or provide a customer-managed role with --role-arn.",
148
+ )
149
+
150
+ iam.put_role_policy(
151
+ RoleName=role_name,
152
+ PolicyName=AB_TEST_ROLE_POLICY_NAME,
153
+ PolicyDocument=_compact(_execution_policy(region, account_id)),
154
+ )
155
+ delay = propagation_delay_ms if propagation_delay_ms is not None else IAM_PROPAGATION_DELAY_MS
156
+ sleep(delay / 1000)
157
+ return role_arn
158
+
159
+
160
+ def delete_ab_test_role(region: str, role_arn: str) -> None:
161
+ """Best-effort role cleanup: delete the inline policy then the role."""
162
+ iam = create_aws_client("iam", region)
163
+ role_name = role_name_from_arn(role_arn)
164
+ try:
165
+ iam.delete_role_policy(RoleName=role_name, PolicyName=AB_TEST_ROLE_POLICY_NAME)
166
+ except Exception: # noqa: BLE001, S110
167
+ pass
168
+ try:
169
+ iam.delete_role(RoleName=role_name)
170
+ except Exception: # noqa: BLE001, S110
171
+ pass
172
+
173
+
174
+ def resolve_gateway_arn(ref: str, deployed: dict[str, Any] | None) -> str | None:
175
+ if ref.startswith("arn:"):
176
+ return ref
177
+ m = re.fullmatch(r"\{\{gateway:(.+)\}\}", ref)
178
+ name = m.group(1) if m else ref
179
+ deployed = deployed or {}
180
+ mcp_gw = ((deployed.get("mcp") or {}).get("gateways") or {}).get(name) if name else None
181
+ if mcp_gw:
182
+ return mcp_gw.get("gatewayArn")
183
+ http_gw = (deployed.get("gateways") or {}).get(name) if name else None
184
+ if http_gw:
185
+ return http_gw.get("gatewayArn")
186
+ return None
187
+
188
+
189
+ def resolve_config_bundle_arn(ref: str, deployed: dict[str, Any] | None) -> str | None:
190
+ if ref.startswith("arn:"):
191
+ return ref
192
+ bundle = ((deployed or {}).get("configBundles") or {}).get(ref)
193
+ return bundle.get("bundleArn") if bundle else None
194
+
195
+
196
+ def resolve_config_bundle_version(bundle_ref: str, version_ref: str, deployed: dict[str, Any] | None) -> str | None:
197
+ if version_ref != "LATEST":
198
+ return version_ref
199
+ if bundle_ref.startswith("arn:"):
200
+ return None
201
+ bundle = ((deployed or {}).get("configBundles") or {}).get(bundle_ref)
202
+ return bundle.get("versionId") if bundle else None
203
+
204
+
205
+ def resolve_online_eval_arn(ref: str, deployed: dict[str, Any] | None) -> str | None:
206
+ if ref.startswith("arn:"):
207
+ return ref
208
+ config = ((deployed or {}).get("onlineEvalConfigs") or {}).get(ref)
209
+ return config.get("onlineEvaluationConfigArn") if config else None
210
+
211
+
212
+ def resolve_runtime_target_names(gateway_name: str | None, runtime_name: str | None, project: dict[str, Any]) -> list:
213
+ """Every httpRuntime target on the gateway that fronts the runtime, in spec order."""
214
+ if not gateway_name or not runtime_name:
215
+ return []
216
+ gateway = next((g for g in project.get("agentCoreGateways") or [] if g.get("name") == gateway_name), None)
217
+ return [
218
+ t["name"]
219
+ for t in (gateway or {}).get("targets") or []
220
+ if t.get("targetType") == "httpRuntime" and (t.get("httpRuntime") or {}).get("runtime") == runtime_name
221
+ ]
File without changes
@@ -0,0 +1,68 @@
1
+ """Batch-evaluation start-time helpers (port of operations/jobs/batch-evaluation/build-source.ts)."""
2
+
3
+ import re
4
+ import time
5
+ from typing import Any
6
+
7
+ from agentcore.aws.cloudwatch import resolve_endpoint_name, runtime_log_group
8
+ from agentcore.lib import ValidationError
9
+ from agentcore.operations.jobs.shared.constants import BATCH_EVAL_NAME_REGEX
10
+ from agentcore.operations.jobs.shared.format import iso_from_ms, iso_now
11
+
12
+
13
+ def resolve_batch_evaluator_ids(deployed_state: dict[str, Any], agent: str, evaluators: list[str]) -> list[str]:
14
+ """Evaluator references -> the SHORT ids the batch API expects (Builtin.*, ARNs, deployed names)."""
15
+ target_resources = next(
16
+ (
17
+ (t or {}).get("resources")
18
+ for t in (deployed_state.get("targets") or {}).values()
19
+ if (((t or {}).get("resources") or {}).get("runtimes") or {}).get(agent) is not None
20
+ ),
21
+ None,
22
+ )
23
+ out: list[str] = []
24
+ for name in evaluators:
25
+ short = name.split("evaluator/")[-1] if "evaluator/" in name else name
26
+ if short.startswith("Builtin."):
27
+ out.append(short)
28
+ continue
29
+ deployed = ((target_resources or {}).get("evaluators") or {}).get(short)
30
+ out.append(deployed["evaluatorId"] if deployed and deployed.get("evaluatorId") else short)
31
+ return out
32
+
33
+
34
+ def build_cloud_watch_source(project_name: str, agent: str, runtime_id: str, endpoint: str | None) -> dict[str, str]:
35
+ """CloudWatch service name + log group for the agent's runtime traces."""
36
+ endpoint_name = resolve_endpoint_name(endpoint)
37
+ return {
38
+ "serviceName": f"{project_name}_{agent}.{endpoint_name}",
39
+ "logGroupName": runtime_log_group(runtime_id, endpoint),
40
+ }
41
+
42
+
43
+ def resolve_batch_eval_name(name: str | None, project_name: str, agent: str) -> str:
44
+ """Validate an explicit name or auto-generate one."""
45
+ if name:
46
+ if not BATCH_EVAL_NAME_REGEX.match(name):
47
+ raise ValidationError(
48
+ "Batch evaluation name must start with a letter and contain only letters, digits, and "
49
+ f'underscores (max 48 chars). Got: "{name}"'
50
+ )
51
+ return name
52
+ return re.sub(r"[^a-zA-Z0-9_]", "_", f"{project_name}_{agent}_{int(time.time() * 1000)}")[:48]
53
+
54
+
55
+ def build_cloud_watch_filter_config(session_ids: list[str] | None, lookback_days: int | None) -> dict | None:
56
+ """sessionIds take precedence over a lookback timeRange; None when neither is given."""
57
+ effective = list(dict.fromkeys(session_ids or []))
58
+ if effective:
59
+ return {"sessionIds": effective}
60
+ if lookback_days:
61
+ now_ms = time.time() * 1000
62
+ return {
63
+ "timeRange": {
64
+ "startTime": iso_from_ms(now_ms - lookback_days * 24 * 60 * 60 * 1000),
65
+ "endTime": iso_now(),
66
+ }
67
+ }
68
+ return None
@@ -0,0 +1,95 @@
1
+ """Dataset Phase-1 for batch evaluation (port of operations/jobs/batch-evaluation/dataset-phase1.ts).
2
+
3
+ Invokes the agent against every dataset scenario, waits for CloudWatch ingestion, and returns the
4
+ sessionIds + ground-truth sessionMetadata to hand to ``engine.start('batch-evaluation', ...)``.
5
+ """
6
+
7
+ import time
8
+ from collections.abc import Callable
9
+ from typing import Any
10
+
11
+ from agentcore.lib import ConfigIO
12
+ from agentcore.lib.errors.types import to_error
13
+ from agentcore.lib.result import Err, Ok
14
+ from agentcore.operations.eval.shared.dataset_session_provider import run_dataset_scenarios
15
+
16
+ # Delay before submitting batch eval to allow CloudWatch span ingestion. Matches the SDK default.
17
+ BATCH_INGESTION_DELAY_MS = 180_000
18
+
19
+
20
+ def _resolve_agent_context(**kwargs: Any) -> Any:
21
+ from agentcore.operations.invoke.resolve_agent_context import resolve_agent_context
22
+
23
+ return resolve_agent_context(**kwargs)
24
+
25
+
26
+ def _ground_truth(scenario: dict[str, Any] | None) -> dict[str, Any] | None:
27
+ if scenario is None:
28
+ return None
29
+ inline: dict[str, Any] = {}
30
+ if scenario.get("assertions"):
31
+ inline["assertions"] = [{"text": a} for a in scenario["assertions"]]
32
+ if scenario.get("expected_trajectory"):
33
+ inline["expectedTrajectory"] = {"toolNames": scenario["expected_trajectory"]}
34
+ turns = scenario.get("turns") or []
35
+ if any(t.get("expectedResponse") for t in turns):
36
+ inline["turns"] = [
37
+ {
38
+ "input": {"prompt": t.get("input")},
39
+ **({"expectedResponse": {"text": t["expectedResponse"]}} if t.get("expectedResponse") else {}),
40
+ }
41
+ for t in turns
42
+ ]
43
+ return {"inline": inline}
44
+
45
+
46
+ def run_dataset_phase1(
47
+ *,
48
+ agent: str,
49
+ dataset_name: str,
50
+ dataset_version: str | None = None,
51
+ endpoint: str | None = None,
52
+ config_io: ConfigIO | None = None,
53
+ on_progress: Callable[[str, str], None] | None = None,
54
+ ingestion_delay_ms: int | None = None,
55
+ sleep: Callable[[float], None] = time.sleep,
56
+ ) -> Ok | Err:
57
+ """Ok({"sessionIds": [...], "sessionMetadata": [...]}) or Err(error)."""
58
+ config_io = config_io or ConfigIO()
59
+ progress = on_progress or (lambda _p, _m: None)
60
+ try:
61
+ agent_context = _resolve_agent_context(
62
+ project=config_io.read_project_spec(),
63
+ deployed_state=config_io.read_deployed_state(),
64
+ aws_targets=config_io.resolve_aws_deployment_targets(),
65
+ agent_name=agent,
66
+ endpoint=endpoint,
67
+ )
68
+ progress("invoking", f'Invoking agent with dataset "{dataset_name}"...')
69
+ dataset_result = run_dataset_scenarios(
70
+ agent_context=agent_context,
71
+ dataset_name=dataset_name,
72
+ version=dataset_version,
73
+ config_base_dir=config_io.get_config_root(),
74
+ on_progress=progress,
75
+ )
76
+ successful = [r for r in dataset_result["scenarioResults"] if r["status"] == "success"]
77
+ if not successful:
78
+ return Err(Exception("All scenarios failed during invocation. No sessions to evaluate."))
79
+
80
+ session_ids = [r["sessionId"] for r in successful]
81
+ session_metadata = []
82
+ for r in successful:
83
+ scenario = next((s for s in dataset_result["scenarios"] if s["scenario_id"] == r["scenarioId"]), None)
84
+ entry: dict[str, Any] = {"sessionId": r["sessionId"], "testScenarioId": r["scenarioId"]}
85
+ gt = _ground_truth(scenario)
86
+ if gt is not None:
87
+ entry["groundTruth"] = gt
88
+ session_metadata.append(entry)
89
+
90
+ progress("invoking", f"✓ {len(successful)} sessions ready for batch evaluation")
91
+ progress("ingesting", "Waiting 180s for CloudWatch span ingestion...")
92
+ sleep((ingestion_delay_ms if ingestion_delay_ms is not None else BATCH_INGESTION_DELAY_MS) / 1000)
93
+ return Ok({"sessionIds": session_ids, "sessionMetadata": session_metadata})
94
+ except Exception as exc: # noqa: BLE001
95
+ return Err(to_error(exc))
@@ -0,0 +1,58 @@
1
+ """Presentation helpers for batch-evaluation jobs (port of operations/jobs/batch-evaluation/format.ts)."""
2
+
3
+ from typing import Any
4
+
5
+ import typer
6
+
7
+ from agentcore.operations.jobs.shared.format import format_job_date, to_fixed
8
+
9
+
10
+ def print_batch_evaluation_history(records: list[dict[str, Any]]) -> None:
11
+ if not records:
12
+ typer.echo("No batch evaluation jobs found. Run `agentcore run batch-evaluation` to create one.")
13
+ return
14
+ typer.echo(f"\n{'Date'.ljust(22)} {'Status'.ljust(22)} {'Evaluators'.ljust(28)} ID")
15
+ typer.echo("─" * 100)
16
+ for r in records:
17
+ typer.echo(
18
+ f"{format_job_date(r.get('createdAt')).ljust(22)} {str(r.get('status')).ljust(22)} "
19
+ f"{', '.join(r.get('evaluators') or []).ljust(28)} {r['id']}"
20
+ )
21
+ typer.echo("")
22
+
23
+
24
+ def summary_line(s: dict[str, Any]) -> str:
25
+ avg = (s.get("statistics") or {}).get("averageScore")
26
+ failed = f" ({s['totalFailed']} failed)" if s.get("totalFailed") else ""
27
+ return f" {s.get('evaluatorId')}: {to_fixed(avg, 2) if avg is not None else 'N/A'}{failed}"
28
+
29
+
30
+ def print_batch_evaluation_detail(record: dict[str, Any]) -> None:
31
+ typer.echo(f"\nBatch evaluation: {record['id']}")
32
+ typer.echo(f"Name: {record.get('name')}")
33
+ typer.echo(f"Status: {record.get('status')}")
34
+ typer.echo(f"Agent: {record.get('agent')}")
35
+ typer.echo(f"Evaluators: {', '.join(record.get('evaluators') or [])}")
36
+ typer.echo(f"Started: {format_job_date(record.get('createdAt'))}")
37
+ if record.get("completedAt"):
38
+ typer.echo(f"Completed: {format_job_date(record['completedAt'])}")
39
+ if record.get("source"):
40
+ typer.echo(f"Source: {record['source']}")
41
+
42
+ summaries = (record.get("evaluationResults") or {}).get("evaluatorSummaries")
43
+ if summaries:
44
+ typer.echo("\nResults:")
45
+ for s in summaries:
46
+ typer.echo(summary_line(s))
47
+ elif record.get("results"):
48
+ typer.echo("\nResults:")
49
+ for r in record["results"]:
50
+ score = r.get("score")
51
+ typer.echo(
52
+ f" {r.get('evaluatorId')}: {to_fixed(score, 2) if score is not None else (r.get('label') or 'N/A')}"
53
+ )
54
+ else:
55
+ typer.echo("\nResults not yet available.")
56
+ if record.get("logFilePath"):
57
+ typer.echo(f"\nLog: {record['logFilePath']}")
58
+ typer.echo("")
@@ -0,0 +1,203 @@
1
+ """Batch-evaluation job handler (port of operations/jobs/batch-evaluation/handler.ts).
2
+
3
+ - create(): resolve agent + evaluators, build the CloudWatch data source, ONE StartBatchEvaluation.
4
+ - refresh(): GET latest status (404 -> NOT_FOUND); on terminal status fetch per-session scores
5
+ from the CloudWatch output log once (``resultsFetched``).
6
+ - stop(): StopBatchEvaluation. archive(): DeleteBatchEvaluation.
7
+ """
8
+
9
+ import json
10
+ from typing import Any
11
+
12
+ from agentcore.aws import agentcore_batch_evaluation as api
13
+ from agentcore.aws.account import create_aws_client
14
+ from agentcore.lib import ConfigIO, JobNotFoundError, ResourceNotFoundError
15
+ from agentcore.lib.errors.types import to_error
16
+ from agentcore.lib.result import Err, Ok
17
+ from agentcore.lib.utils.json_format import to_json_string
18
+ from agentcore.logging.exec_logger import ExecLogger
19
+ from agentcore.operations.jobs.batch_evaluation.build_source import (
20
+ build_cloud_watch_filter_config,
21
+ build_cloud_watch_source,
22
+ resolve_batch_eval_name,
23
+ resolve_batch_evaluator_ids,
24
+ )
25
+ from agentcore.operations.jobs.shared.constants import NOT_FOUND_STATUS
26
+ from agentcore.operations.jobs.shared.format import iso_now
27
+ from agentcore.operations.jobs.shared.region import region_of, resolve_job_region
28
+ from agentcore.operations.jobs.shared.resolve_agent_state import deployed_dict, resolve_agent_state
29
+ from agentcore.operations.jobs.shared.storage import drop_undefined
30
+
31
+ _TERMINAL = ("COMPLETED", "COMPLETED_WITH_ERRORS", "FAILED", "STOPPED", "CANCELLED")
32
+
33
+
34
+ def new_logger(command: str) -> ExecLogger | None:
35
+ try:
36
+ return ExecLogger(command)
37
+ except Exception: # noqa: BLE001 - logger creation is non-fatal
38
+ return None
39
+
40
+
41
+ def fetch_results_from_cloud_watch(region: str, log_group_name: str, log_stream_name: str) -> list[dict[str, Any]]:
42
+ """Per-session evaluation scores from the batch's CloudWatch output log stream."""
43
+ client = create_aws_client("logs", region)
44
+ response = client.get_log_events(logGroupName=log_group_name, logStreamName=log_stream_name, startFromHead=True)
45
+ results: list[dict[str, Any]] = []
46
+ for event in response.get("events") or []:
47
+ message = event.get("message")
48
+ if not message:
49
+ continue
50
+ try:
51
+ parsed = json.loads(message)
52
+ except ValueError:
53
+ continue
54
+ if not isinstance(parsed, dict):
55
+ continue
56
+ attrs = parsed.get("attributes") or {}
57
+ evaluator_id = attrs.get("gen_ai.evaluation.name")
58
+ if not evaluator_id:
59
+ continue
60
+ results.append(
61
+ drop_undefined(
62
+ {
63
+ "evaluatorId": evaluator_id,
64
+ "score": attrs.get("gen_ai.evaluation.score.value"),
65
+ "label": attrs.get("gen_ai.evaluation.score.label"),
66
+ "explanation": attrs.get("gen_ai.evaluation.explanation"),
67
+ }
68
+ )
69
+ )
70
+ return results
71
+
72
+
73
+ def create(opts: dict[str, Any], config_io: ConfigIO) -> Ok | Err:
74
+ logger = new_logger("batch-evaluate")
75
+ try:
76
+ if logger:
77
+ logger.start_step("Load project config")
78
+ project = config_io.read_project_spec()
79
+ deployed_state = deployed_dict(config_io.read_deployed_state())
80
+ aws_targets = config_io.resolve_aws_deployment_targets()
81
+ region = resolve_job_region(opts.get("region"), aws_targets)
82
+ if logger:
83
+ logger.end_step("success")
84
+ logger.start_step("Resolve agent")
85
+ agent = opts["agent"]
86
+ agent_state = resolve_agent_state(deployed_state, agent)
87
+ if not agent_state:
88
+ err = ResourceNotFoundError(f'Agent "{agent}" not deployed. Run `agentcore deploy` first.')
89
+ if logger:
90
+ logger.end_step("error", err.message)
91
+ logger.finalize(False)
92
+ return Err(err)
93
+ source = build_cloud_watch_source(project.name, agent, agent_state["runtimeId"], opts.get("endpoint"))
94
+ if logger:
95
+ logger.log(f"Service name: {source['serviceName']}")
96
+ logger.log(f"Log group: {source['logGroupName']}")
97
+ logger.end_step("success")
98
+
99
+ eval_name = resolve_batch_eval_name(opts.get("name"), project.name, agent)
100
+ resolved = resolve_batch_evaluator_ids(deployed_state, agent, opts.get("evaluators") or [])
101
+
102
+ session_metadata = opts.get("sessionMetadata")
103
+ metadata_ids = [m.get("sessionId") for m in (session_metadata or []) if m.get("sessionId")]
104
+ effective_ids = list(dict.fromkeys([*(opts.get("sessionIds") or []), *metadata_ids]))
105
+ filter_config = build_cloud_watch_filter_config(effective_ids, opts.get("lookbackDays"))
106
+
107
+ if logger:
108
+ logger.start_step("Start batch evaluation")
109
+ on_progress = opts.get("onProgress")
110
+ if on_progress:
111
+ on_progress("starting", f'Starting batch evaluation "{eval_name}"...')
112
+ cloud_watch: dict[str, Any] = {
113
+ "serviceNames": [source["serviceName"]],
114
+ "logGroupNames": [source["logGroupName"]],
115
+ }
116
+ if filter_config:
117
+ cloud_watch["filterConfig"] = filter_config
118
+ start = api.start_batch_evaluation(
119
+ region=region,
120
+ name=eval_name,
121
+ evaluators=[{"evaluatorId": i} for i in resolved],
122
+ data_source_config={"cloudWatchLogs": cloud_watch},
123
+ evaluation_metadata={"sessionMetadata": session_metadata} if session_metadata else None,
124
+ kms_key_arn=opts.get("kmsKeyArn") or None,
125
+ client_token=api.generate_client_token(),
126
+ )
127
+ if logger:
128
+ logger.log(f"Response: {to_json_string(start)}")
129
+ logger.end_step("success")
130
+ if on_progress:
131
+ on_progress("started", f"Batch evaluation created: {start['batchEvaluationId']} ({start['status']})")
132
+ if logger:
133
+ logger.finalize(True)
134
+
135
+ record: dict[str, Any] = {
136
+ "type": "batch-evaluation",
137
+ "id": start["batchEvaluationId"],
138
+ "arn": start["batchEvaluationArn"],
139
+ "status": start["status"],
140
+ "createdAt": start.get("createdAt") or iso_now(),
141
+ "agent": agent,
142
+ "logFilePath": logger.log_file_path if logger else None,
143
+ "name": eval_name,
144
+ "evaluators": resolved,
145
+ "source": opts.get("source"),
146
+ "dataset": opts.get("dataset"),
147
+ }
148
+ if opts.get("kmsKeyArn"):
149
+ record["kmsKeyArn"] = opts["kmsKeyArn"]
150
+ return Ok(drop_undefined(record))
151
+ except Exception as exc: # noqa: BLE001
152
+ if logger:
153
+ logger.finalize(False)
154
+ return Err(to_error(exc))
155
+
156
+
157
+ def refresh(record: dict[str, Any]) -> Ok | Err:
158
+ region = region_of(record["arn"])
159
+ try:
160
+ response = api.get_batch_evaluation(region=region, batch_evaluation_id=record["id"])
161
+ except JobNotFoundError:
162
+ return Ok({**record, "status": NOT_FOUND_STATUS, "resultsFetched": True})
163
+ except Exception as exc: # noqa: BLE001
164
+ return Err(to_error(exc))
165
+
166
+ updated = {
167
+ **record,
168
+ "status": response["status"],
169
+ "completedAt": response.get("updatedAt") or record.get("completedAt"),
170
+ "evaluationResults": response.get("evaluationResults") or record.get("evaluationResults"),
171
+ "kmsKeyArn": response.get("kmsKeyArn") or record.get("kmsKeyArn"),
172
+ }
173
+ terminal = response["status"] in _TERMINAL
174
+ cw = (response.get("outputConfig") or {}).get("cloudWatchConfig")
175
+ if terminal and not record.get("resultsFetched") and cw:
176
+ try:
177
+ results = fetch_results_from_cloud_watch(region, cw["logGroupName"], cw["logStreamName"])
178
+ if results or not record.get("results"):
179
+ updated["results"] = results
180
+ updated["resultsFetched"] = True
181
+ except Exception: # noqa: BLE001, S110 - leave resultsFetched false so the next read retries
182
+ pass
183
+ elif terminal and not cw:
184
+ updated["resultsFetched"] = True
185
+ return Ok(drop_undefined(updated))
186
+
187
+
188
+ def stop(record: dict[str, Any]) -> Ok | Err:
189
+ try:
190
+ api.stop_batch_evaluation(region=region_of(record["arn"]), batch_evaluation_id=record["id"])
191
+ return Ok(None)
192
+ except Exception as exc: # noqa: BLE001
193
+ return Err(to_error(exc))
194
+
195
+
196
+ def archive(record: dict[str, Any]) -> Ok | Err:
197
+ try:
198
+ api.delete_batch_evaluation(region=region_of(record["arn"]), batch_evaluation_id=record["id"])
199
+ return Ok(None)
200
+ except JobNotFoundError:
201
+ return Ok(None)
202
+ except Exception as exc: # noqa: BLE001
203
+ return Err(to_error(exc))
File without changes