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
File without changes
File without changes
@@ -0,0 +1,39 @@
1
+ """Helpers shared by the eval/jobs command modules (run, view, history, pause/resume, ...)."""
2
+
3
+ from collections.abc import Callable
4
+ from typing import Any
5
+
6
+ import typer
7
+
8
+ from agentcore.cli.commands.logs.guards import require_project
9
+ from agentcore.lib.result import Err, Ok
10
+ from agentcore.lib.utils.json_format import to_json_string
11
+
12
+ __all__ = ["fail_early", "print_json", "red", "require_project", "result_json"]
13
+
14
+
15
+ def print_json(payload: dict[str, Any]) -> None:
16
+ """``console.log(JSON.stringify(payload))`` with undefined (None) top-level keys dropped."""
17
+ typer.echo(to_json_string({k: v for k, v in payload.items() if v is not None}, None))
18
+
19
+
20
+ def red(message: str) -> None:
21
+ """Ink ``<Text color="red">`` (stdout)."""
22
+ typer.secho(message, fg=typer.colors.RED)
23
+
24
+
25
+ def fail_early(as_json: bool, error: str) -> None:
26
+ """Upstream's pre-validation pattern: JSON error line or red text, then exit 1."""
27
+ if as_json:
28
+ print_json({"success": False, "error": error})
29
+ else:
30
+ red(error)
31
+ raise typer.Exit(1)
32
+
33
+
34
+ def result_json(result: Ok | Err, value_key: Callable[[Any], dict] | None = None) -> dict[str, Any]:
35
+ from agentcore.lib import serialize_result
36
+
37
+ if result.success and value_key is not None:
38
+ return {"success": True, **value_key(result.value)}
39
+ return serialize_result(result)
@@ -0,0 +1,639 @@
1
+ """Prompt-based replacements for the `run` TUI flows.
2
+
3
+ Question order follows tui/screens/run-eval/RunBatchEvalFlow.tsx, tui/screens/recommendation/*
4
+ and tui/screens/run-ab-test/RunABTestFlow.tsx.
5
+ """
6
+
7
+ import json
8
+ import os
9
+ import re
10
+ from typing import Any
11
+
12
+ import typer
13
+
14
+ from agentcore.aws import agentcore_control as control
15
+ from agentcore.aws import agentcore_datasets as datasets_api
16
+ from agentcore.aws import region as _region
17
+ from agentcore.aws.account import validate_aws_credentials
18
+ from agentcore.cli import interactive
19
+ from agentcore.cli.errors import get_error_message
20
+ from agentcore.lib import ConfigIO
21
+ from agentcore.lib.schemas.io.config_io import to_jsonable
22
+ from agentcore.operations import resolve_agent as _resolve_agent
23
+ from agentcore.operations.dataset.resolve_dataset import resolve_dataset
24
+ from agentcore.operations.eval.run_eval import discover_sessions
25
+ from agentcore.operations.jobs import create_job_engine, run_dataset_phase1
26
+ from agentcore.operations.jobs.shared.format import parse_int, parse_js_date
27
+ from agentcore.schema import is_valid_kms_key_arn
28
+
29
+ Choice = interactive.Choice
30
+ DEFAULT_LOOKBACK_DAYS = 7
31
+ _KMS_INVALID = "Invalid KMS key ARN (e.g. arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012)"
32
+
33
+
34
+ def _require_creds() -> None:
35
+ try:
36
+ validate_aws_credentials()
37
+ except Exception as exc: # noqa: BLE001
38
+ typer.secho("AWS credentials required", fg=typer.colors.RED, err=True)
39
+ typer.echo(get_error_message(exc), err=True)
40
+ raise typer.Exit(1) from None
41
+
42
+
43
+ def _error(message: str, detail: str | None = None) -> None:
44
+ typer.secho(message, fg=typer.colors.RED, err=True)
45
+ if detail:
46
+ typer.echo(detail, err=True)
47
+ raise typer.Exit(1)
48
+
49
+
50
+ def _evaluator_choices(evaluators: list[dict[str, Any]]) -> list[Choice]:
51
+ return [
52
+ Choice(
53
+ e["evaluatorName"],
54
+ e["evaluatorArn"],
55
+ "Built-in evaluator"
56
+ if e.get("evaluatorType") == "Builtin"
57
+ else (e.get("description") or "Custom evaluator"),
58
+ )
59
+ for e in evaluators
60
+ ]
61
+
62
+
63
+ def _validate_days(value: str) -> str | None:
64
+ days = parse_int(value)
65
+ if days is None:
66
+ return "Must be a number"
67
+ return None if 1 <= days <= 90 else "Must be between 1 and 90"
68
+
69
+
70
+ def _validate_kms(value: str) -> str | None:
71
+ return None if not value or is_valid_kms_key_arn(value) else _KMS_INVALID
72
+
73
+
74
+ def _session_label(session: dict[str, Any]) -> tuple[str, str]:
75
+ parsed = parse_js_date(session.get("firstSeen")) if session.get("firstSeen") else None
76
+ date = ""
77
+ if parsed is not None:
78
+ local = parsed.astimezone()
79
+ hour12 = local.hour % 12 or 12
80
+ months = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
81
+ date = f"{months[local.month - 1]} {local.day}, {hour12:02d}:{local.minute:02d} {'AM' if local.hour < 12 else 'PM'}"
82
+ return session["sessionId"], f"{session.get('spanCount', 0)} spans · {date}"
83
+
84
+
85
+ def _pick_sessions(runtime_id: str, region: str, days: int, title: str) -> list[str]:
86
+ typer.echo("Discovering sessions...")
87
+ sessions = discover_sessions(runtime_id=runtime_id, region=region, lookback_days=days)
88
+ if not sessions:
89
+ _error(f"No sessions found in the last {days} day(s). Invoke the agent first and wait for traces to propagate.")
90
+ count = len(sessions)
91
+ typer.echo(f"Found {count} session{'' if count == 1 else 's'} — select one or more")
92
+ while True:
93
+ picked = interactive.checkbox(
94
+ title, [Choice(_session_label(s)[0], s["sessionId"], _session_label(s)[1]) for s in sessions]
95
+ )
96
+ if picked:
97
+ return picked
98
+ typer.echo("Select at least one session.", err=True)
99
+
100
+
101
+ def _ground_truth(session_ids: list[str]) -> list[dict[str, Any]] | None:
102
+ mode = interactive.select(
103
+ "Ground truth (optional)",
104
+ [
105
+ Choice("Skip", "skip", "No ground truth"),
106
+ Choice("Load from file", "file", "JSON file with session metadata and ground truth"),
107
+ Choice("Enter manually", "inline", "Type assertions, trajectory, and expected response"),
108
+ ],
109
+ )
110
+ if mode == "skip":
111
+ return None
112
+ if mode == "file":
113
+ typer.echo("Select a JSON file with session ground truth (assertions, expected trajectory, turns).")
114
+ while True:
115
+ path = interactive.text("path/to/ground-truth.json")
116
+ try:
117
+ with open(os.path.abspath(os.path.expanduser(path.strip())), encoding="utf-8") as fh:
118
+ parsed = json.load(fh)
119
+ metadata = parsed if isinstance(parsed, list) else (parsed or {}).get("sessionMetadata")
120
+ if not isinstance(metadata, list):
121
+ typer.secho('File must be a JSON array or contain a "sessionMetadata" array', fg="red")
122
+ continue
123
+ return metadata
124
+ except Exception as exc: # noqa: BLE001
125
+ typer.secho(f"Failed to load file: {exc}", fg="red")
126
+ label = session_ids[0] if len(session_ids) == 1 else f"{len(session_ids)} sessions"
127
+ typer.echo(f"Session: {label}")
128
+ typer.echo("All fields are optional. Press Enter on empty to skip to next section.")
129
+ assertions = _collect_lines("Assertions:")
130
+ trajectory = _collect_lines("Expected trajectory:")
131
+ response = interactive.text("Expected response (targets last trace):")
132
+ inline: dict[str, Any] = {}
133
+ if assertions:
134
+ inline["assertions"] = [{"text": a} for a in assertions]
135
+ if trajectory:
136
+ inline["expectedTrajectory"] = {"toolNames": trajectory}
137
+ if response:
138
+ inline["turns"] = [{"input": {"prompt": ""}, "expectedResponse": {"text": response}}]
139
+ return [{"sessionId": sid, "groundTruth": {"inline": inline}} for sid in session_ids]
140
+
141
+
142
+ def _collect_lines(label: str) -> list[str]:
143
+ values: list[str] = []
144
+ while True:
145
+ value = interactive.text(f"{label} ({len(values) + 1})")
146
+ if not value:
147
+ return values
148
+ values.append(value)
149
+
150
+
151
+ # ──────────────────────────────────────────────────────────────────────────────
152
+ # Batch evaluation
153
+ # ──────────────────────────────────────────────────────────────────────────────
154
+
155
+
156
+ def run_batch_eval_wizard() -> None:
157
+ _require_creds()
158
+ context = _resolve_agent.load_deployed_project_config()
159
+ targets = context.aws_targets or []
160
+ region = (targets[0].region if targets else None) or _region.detect_region().region
161
+ evaluators = control.list_evaluators(region=region)["evaluators"]
162
+ deployed = to_jsonable(context.deployed_state)
163
+ deployed_names: set[str] = set()
164
+ runtime_ids: dict[str, str] = {}
165
+ for target in (deployed.get("targets") or {}).values():
166
+ for name, state in (((target or {}).get("resources") or {}).get("runtimes") or {}).items():
167
+ deployed_names.add(name)
168
+ runtime_ids[name] = state["runtimeId"]
169
+ project = to_jsonable(context.project)
170
+ agents = [r for r in project.get("runtimes") or [] if r["name"] in deployed_names]
171
+ if not agents:
172
+ _error(
173
+ "No agents found in project. Run `agentcore add agent` first."
174
+ if not project.get("runtimes")
175
+ else "No deployed agents found. Run `agentcore deploy` first."
176
+ )
177
+ if not evaluators:
178
+ _error("No evaluators found in your account. Create an evaluator first.")
179
+
180
+ source = interactive.select(
181
+ "Evaluation source:",
182
+ [
183
+ Choice("Dataset", "dataset", "Invoke agent with dataset scenarios"),
184
+ Choice("Historical traces", "traces", "Evaluate existing sessions"),
185
+ ],
186
+ )
187
+ dataset = dataset_version = None
188
+ if source == "dataset":
189
+ datasets = project.get("datasets") or []
190
+ labels = {
191
+ "AGENTCORE_EVALUATION_PREDEFINED_V1": "Predefined Turns",
192
+ "AGENTCORE_EVALUATION_SIMULATED_V1": "Actor Simulator",
193
+ }
194
+ if len(datasets) == 1:
195
+ dataset = datasets[0]["name"]
196
+ elif datasets:
197
+ dataset = interactive.select(
198
+ "Select dataset:",
199
+ [Choice(d["name"], d["name"], labels.get(d["schemaType"], d["schemaType"])) for d in datasets],
200
+ )
201
+ if dataset:
202
+ versions = [Choice("Local file", "local", "fastest iteration, no push required")]
203
+ try:
204
+ resolved = resolve_dataset(dataset)
205
+ listed = datasets_api.list_dataset_versions(region=resolved.region, dataset_id=resolved.dataset_id)
206
+ versions.append(Choice("DRAFT", "DRAFT", "latest pushed content"))
207
+ for v in sorted(listed.get("versions") or [], key=lambda v: v.get("createdAt") or 0, reverse=True):
208
+ versions.append(
209
+ Choice(
210
+ f"Version {v['datasetVersion']}", v["datasetVersion"], f"{v.get('exampleCount')} examples"
211
+ )
212
+ )
213
+ except Exception: # noqa: BLE001, S110 - not deployed yet: local only
214
+ pass
215
+ picked = interactive.select(f"Select version for {dataset}:", versions)
216
+ dataset_version = None if picked == "local" else picked
217
+
218
+ agent = agents[0]["name"]
219
+ if len(agents) > 1:
220
+ agent = interactive.select(
221
+ "Select agent to evaluate", [Choice(a["name"], a["name"], a.get("build")) for a in agents]
222
+ )
223
+ while True:
224
+ chosen = interactive.checkbox("Select evaluators", _evaluator_choices(evaluators))
225
+ if chosen:
226
+ break
227
+ typer.echo("Select at least one evaluator.", err=True)
228
+ names = [e["evaluatorName"] for e in evaluators if e["evaluatorArn"] in chosen]
229
+
230
+ days = DEFAULT_LOOKBACK_DAYS
231
+ session_ids: list[str] = []
232
+ session_metadata = None
233
+ if source == "traces":
234
+ typer.echo("Note: Traces may take 5–10 min to appear after agent invocations.")
235
+ days = (
236
+ parse_int(
237
+ interactive.text("Lookback window (days)", default=str(DEFAULT_LOOKBACK_DAYS), validate=_validate_days)
238
+ )
239
+ or DEFAULT_LOOKBACK_DAYS
240
+ )
241
+ session_ids = _pick_sessions(runtime_ids[agent], region, days, "Select sessions to evaluate")
242
+ session_metadata = _ground_truth(session_ids)
243
+ kms = interactive.text("KMS key ARN for encryption (optional, press Enter to skip)", validate=_validate_kms)
244
+ typer.echo("Optional — leave blank for auto-generated name.")
245
+ name = interactive.text("Batch evaluation name")
246
+
247
+ rows = [("Agent", agent), ("Evaluators", ", ".join(names))]
248
+ if source == "dataset":
249
+ rows.append(("Dataset", f"{dataset}@{dataset_version or 'LOCAL'}"))
250
+ else:
251
+ rows += [("Lookback", f"{days} days"), ("Sessions", str(len(session_ids)))]
252
+ if kms:
253
+ rows.append(("KMS Key", kms))
254
+ rows.append(("Name", name or "(auto-generated)"))
255
+ for label, value in rows:
256
+ typer.echo(f" {label}: {value}")
257
+ if not interactive.confirm("Start batch evaluation?", default=True):
258
+ typer.echo("Cancelled.")
259
+ return
260
+
261
+ if source == "dataset":
262
+ phase1 = run_dataset_phase1(
263
+ agent=agent,
264
+ dataset_name=dataset or "",
265
+ dataset_version=dataset_version,
266
+ on_progress=lambda _p, m: typer.echo(m),
267
+ )
268
+ if not phase1.success:
269
+ _error("Batch evaluation failed", str(phase1.error))
270
+ session_ids = phase1.value["sessionIds"]
271
+ session_metadata = phase1.value["sessionMetadata"]
272
+
273
+ engine = create_job_engine(ConfigIO())
274
+ result = engine.start(
275
+ "batch-evaluation",
276
+ {
277
+ "agent": agent,
278
+ "evaluators": chosen,
279
+ "name": name or None,
280
+ "sessionIds": session_ids or None,
281
+ "lookbackDays": days,
282
+ "sessionMetadata": session_metadata,
283
+ "source": "dataset" if dataset else "traces",
284
+ "dataset": {"id": dataset, "version": dataset_version or "LOCAL"} if dataset else None,
285
+ "kmsKeyArn": kms or None,
286
+ },
287
+ )
288
+ if not result.success:
289
+ _error("Batch evaluation failed", str(result.error))
290
+ record = result.value
291
+ typer.secho(f"✓ {record['id']} ({record['status']})", fg=typer.colors.GREEN)
292
+ typer.echo(f"Agent: {agent} Evaluators: {', '.join(names)}")
293
+ typer.echo("\nWhen it completes, view it in Batch Eval Jobs.")
294
+ typer.echo(f"Next: agentcore view batch-evaluation {record['id']}")
295
+
296
+
297
+ # ──────────────────────────────────────────────────────────────────────────────
298
+ # Recommendation
299
+ # ──────────────────────────────────────────────────────────────────────────────
300
+
301
+
302
+ def collect_string_fields(obj: Any, prefix: str, json_path_prefix: str) -> list[dict[str, str]]:
303
+ """All non-empty string leaves with dot paths and JSONPath equivalents (RecommendationFlow)."""
304
+ fields: list[dict[str, str]] = []
305
+ if not isinstance(obj, dict):
306
+ return fields
307
+ for key, value in obj.items():
308
+ path = f"{prefix}.{key}" if prefix else key
309
+ jp = f"{json_path_prefix}.{key}" if json_path_prefix else key
310
+ if isinstance(value, str) and value.strip():
311
+ fields.append({"path": path, "jsonPath": jp, "value": value})
312
+ elif isinstance(value, dict):
313
+ fields.extend(collect_string_fields(value, path, jp))
314
+ return fields
315
+
316
+
317
+ def _bundle_items(deployed: dict[str, Any], project: dict[str, Any]) -> list[dict[str, Any]]:
318
+ items: list[dict[str, Any]] = []
319
+ seen: set[str] = set()
320
+ for target in (deployed.get("targets") or {}).values():
321
+ for name, state in (((target or {}).get("resources") or {}).get("configBundles") or {}).items():
322
+ if name in seen:
323
+ continue
324
+ seen.add(name)
325
+ spec = next((b for b in project.get("configBundles") or [] if b["name"] == name), None)
326
+ items.append(
327
+ {
328
+ "name": name,
329
+ "bundleArn": state["bundleArn"],
330
+ "versionId": state.get("versionId"),
331
+ "fields": collect_string_fields((spec or {}).get("components"), "", "$") if spec else [],
332
+ }
333
+ )
334
+ return items
335
+
336
+
337
+ def _field_title(path: str) -> str:
338
+ segments = path.split(".")
339
+ if "configuration" in segments:
340
+ return ".".join(segments[segments.index("configuration") :])
341
+ return ".".join(segments[-2:])
342
+
343
+
344
+ def run_recommendation_wizard() -> None:
345
+ _require_creds()
346
+ config_io = ConfigIO()
347
+ region = _region.detect_region().region
348
+ deployed = to_jsonable(config_io.read_deployed_state())
349
+ agents: dict[str, dict[str, Any]] = {}
350
+ for target in (deployed.get("targets") or {}).values():
351
+ for name, state in (((target or {}).get("resources") or {}).get("runtimes") or {}).items():
352
+ agents.setdefault(name, state)
353
+ if not agents:
354
+ _error("No deployed agents found. Run `agentcore deploy` first.")
355
+ evaluators = control.list_evaluators(region=region)["evaluators"]
356
+ project = to_jsonable(config_io.read_project_spec())
357
+ bundles = _bundle_items(deployed, project)
358
+
359
+ rec_type = interactive.select(
360
+ "What do you want to optimize?",
361
+ [
362
+ Choice(
363
+ "System Prompt", "SYSTEM_PROMPT_RECOMMENDATION", "Optimize your agent's system prompt based on traces"
364
+ ),
365
+ Choice(
366
+ "Tool Description",
367
+ "TOOL_DESCRIPTION_RECOMMENDATION",
368
+ "Optimize tool descriptions for better tool selection",
369
+ ),
370
+ ],
371
+ )
372
+ is_sys = rec_type == "SYSTEM_PROMPT_RECOMMENDATION"
373
+ agent = interactive.select("Select agent", [Choice(n, n, f"Runtime: {s['runtimeId']}") for n, s in agents.items()])
374
+ chosen_evaluators: list[str] = []
375
+ if is_sys:
376
+ chosen_evaluators = [
377
+ interactive.select(
378
+ "Select evaluator",
379
+ [
380
+ Choice(
381
+ e["evaluatorName"],
382
+ e["evaluatorArn"] or e["evaluatorName"],
383
+ e.get("description") or e.get("evaluatorType"),
384
+ )
385
+ for e in evaluators
386
+ ],
387
+ )
388
+ ]
389
+ input_choices = (
390
+ [
391
+ Choice("Enter inline", "inline", "Type or paste content directly"),
392
+ Choice("Load from file", "file", "Read content from a file path"),
393
+ Choice("Config bundle", "config-bundle", "Use system prompt from a deployed config bundle"),
394
+ ]
395
+ if is_sys
396
+ else [
397
+ Choice("Enter inline", "inline", "Type tool name:description pairs directly"),
398
+ Choice("Config bundle", "config-bundle", "Read tool descriptions from a deployed config bundle"),
399
+ ]
400
+ )
401
+ input_source = interactive.select(
402
+ "How do you want to provide the system prompt?" if is_sys else "How do you want to provide tool descriptions?",
403
+ input_choices,
404
+ )
405
+ content = tools = ""
406
+ bundle_arn = bundle_version = prompt_path = None
407
+ tool_paths: list[dict[str, str]] = []
408
+ if input_source == "config-bundle":
409
+ if not bundles:
410
+ _error("No deployed config bundles found. Run `agentcore add config-bundle` and `agentcore deploy` first.")
411
+ bundle_arn = interactive.select(
412
+ "Select config bundle", [Choice(b["name"], b["bundleArn"], b.get("versionId")) for b in bundles]
413
+ )
414
+ bundle = next(b for b in bundles if b["bundleArn"] == bundle_arn)
415
+ bundle_version = bundle.get("versionId")
416
+ fields = bundle["fields"]
417
+ if not fields:
418
+ _error("No text fields found in this config bundle's configuration.")
419
+ field_choices = [
420
+ Choice(_field_title(f["path"]), f["path"], f["value"][:80] + "…" if len(f["value"]) > 80 else f["value"])
421
+ for f in fields
422
+ ]
423
+ if is_sys:
424
+ picked = interactive.select("Which field contains the system prompt?", field_choices)
425
+ prompt_path = next(f["jsonPath"] for f in fields if f["path"] == picked)
426
+ else:
427
+ if len(fields) == 1:
428
+ picked_paths = [interactive.select("Which field contains the tool description?", field_choices)]
429
+ else:
430
+ picked_paths = []
431
+ while not picked_paths:
432
+ picked_paths = interactive.checkbox("Which fields contain tool descriptions?", field_choices)
433
+ tool_paths = [
434
+ {"toolName": f["path"].split(".")[-1], "toolDescriptionJsonPath": f["jsonPath"]}
435
+ for f in fields
436
+ if f["path"] in picked_paths
437
+ ]
438
+ elif is_sys and input_source == "file":
439
+ content = interactive.text(
440
+ "/path/to/prompt.txt",
441
+ validate=lambda v: None if os.path.isfile(os.path.expanduser(v)) else "File not found",
442
+ )
443
+ content = os.path.abspath(os.path.expanduser(content))
444
+ elif is_sys:
445
+ content = interactive.text("System prompt")
446
+ else:
447
+ typer.echo("Enter tool names and descriptions as comma-separated toolName:description pairs.")
448
+ tools = interactive.text("Tools")
449
+
450
+ trace_source = interactive.select(
451
+ "How do you want to source agent traces?",
452
+ [
453
+ Choice("CloudWatch Logs", "cloudwatch", "Discover traces from agent runtime logs"),
454
+ Choice("Session IDs", "sessions", "Provide specific session IDs manually"),
455
+ ],
456
+ )
457
+ days = (
458
+ parse_int(
459
+ interactive.text("Lookback window (days)", default=str(DEFAULT_LOOKBACK_DAYS), validate=_validate_days)
460
+ )
461
+ or DEFAULT_LOOKBACK_DAYS
462
+ )
463
+ session_ids: list[str] = []
464
+ if trace_source == "sessions":
465
+ session_ids = _pick_sessions(agents[agent]["runtimeId"], region, days, "Select sessions to analyze")
466
+ kms = interactive.text("KMS key ARN for encryption (optional, press Enter to skip)", validate=_validate_kms)
467
+
468
+ rows = [("Type", "System Prompt" if is_sys else "Tool Description"), ("Agent", agent)]
469
+ if chosen_evaluators:
470
+ rows.append(("Evaluator", chosen_evaluators[0]))
471
+ rows += [("Source", input_source), ("Traces", trace_source), ("Lookback", f"{days} days")]
472
+ if kms:
473
+ rows.append(("KMS Key", kms))
474
+ for label, value in rows:
475
+ typer.echo(f" {label}: {value}")
476
+ if not interactive.confirm("Start recommendation?", default=True):
477
+ typer.echo("Cancelled.")
478
+ return
479
+
480
+ engine = create_job_engine(config_io)
481
+ result = engine.start(
482
+ "recommendation",
483
+ {
484
+ "type": rec_type,
485
+ "agent": agent,
486
+ "evaluators": chosen_evaluators,
487
+ "inputSource": input_source,
488
+ "inlineContent": content if input_source == "inline" else None,
489
+ "promptFile": content if input_source == "file" else None,
490
+ "bundleName": bundle_arn,
491
+ "bundleVersion": bundle_version,
492
+ "systemPromptJsonPath": prompt_path,
493
+ "toolDescJsonPaths": tool_paths or None,
494
+ "tools": [t.strip() for t in re.split(r",(?=[a-zA-Z0-9_\-.]+:)", tools) if t.strip()] if tools else None,
495
+ "traceSource": trace_source,
496
+ "lookbackDays": days,
497
+ "sessionIds": session_ids or None,
498
+ "kmsKeyArn": kms or None,
499
+ },
500
+ )
501
+ if not result.success:
502
+ _error("Recommendation failed", str(result.error))
503
+ record = result.value
504
+ typer.secho(f"✓ {record['id']} ({record['status']})", fg=typer.colors.GREEN)
505
+ typer.echo(
506
+ "When it completes, view it in Recommendation Jobs — the new config bundle (if any) will be applied to "
507
+ "agentcore.json automatically."
508
+ )
509
+ typer.echo(f"Next: agentcore view recommendation {record['id']}")
510
+
511
+
512
+ # ──────────────────────────────────────────────────────────────────────────────
513
+ # A/B test
514
+ # ──────────────────────────────────────────────────────────────────────────────
515
+
516
+
517
+ def _load_ab_resources() -> dict[str, Any]:
518
+ config_io = ConfigIO()
519
+ project = to_jsonable(config_io.read_project_spec())
520
+ deployed = to_jsonable(config_io.read_deployed_state())
521
+ bundles: list[str] = []
522
+ gateways: dict[str, None] = {}
523
+ evals: dict[str, None] = {}
524
+ for target in (deployed.get("targets") or {}).values():
525
+ resources = (target or {}).get("resources") or {}
526
+ bundles += list((resources.get("configBundles") or {}).keys())
527
+ gateways.update(dict.fromkeys(((resources.get("mcp") or {}).get("gateways") or {}).keys()))
528
+ gateways.update(dict.fromkeys((resources.get("gateways") or {}).keys()))
529
+ evals.update(dict.fromkeys((resources.get("onlineEvalConfigs") or {}).keys()))
530
+ targets: dict[str, None] = {}
531
+ for gw in project.get("agentCoreGateways") or []:
532
+ for t in gw.get("targets") or []:
533
+ if t.get("targetType") == "httpRuntime":
534
+ targets[t["name"]] = None
535
+ return {"gateways": list(gateways), "bundles": bundles, "targets": list(targets), "onlineEvalConfigs": list(evals)}
536
+
537
+
538
+ def _variant(variant: str, mode: str, resources: dict[str, Any], default_weight: int) -> dict[str, Any]:
539
+ typer.echo(f"{variant} Variant")
540
+ typer.echo("─" * 30)
541
+ out: dict[str, Any] = {}
542
+ if mode == "config-bundle":
543
+ out["bundle"] = interactive.select("Select config bundle:", [Choice(b, b) for b in resources["bundles"]])
544
+ typer.echo("Bundle version (or LATEST):")
545
+ out["version"] = interactive.text("Version", default="LATEST") or "LATEST"
546
+ else:
547
+ out["target"] = interactive.select("Select gateway target:", [Choice(t, t) for t in resources["targets"]])
548
+ out["eval"] = interactive.select(
549
+ "Select online eval (scoped to this endpoint):", [Choice(c, c) for c in resources["onlineEvalConfigs"]]
550
+ )
551
+ typer.echo("Traffic weight (0-100):")
552
+ out["weight"] = parse_int(
553
+ interactive.text(
554
+ "Weight",
555
+ default=str(default_weight),
556
+ validate=lambda v: (
557
+ None if (w := parse_int(v)) is not None and 0 <= w <= 100 else "Must be between 0 and 100"
558
+ ),
559
+ )
560
+ )
561
+ return out
562
+
563
+
564
+ def run_ab_test_wizard() -> None:
565
+ _require_creds()
566
+ resources = _load_ab_resources()
567
+ if not resources["gateways"]:
568
+ _error("No deployed gateway found. Run `agentcore add gateway` and `agentcore deploy` first.")
569
+ mode = interactive.select(
570
+ "Variant mode",
571
+ [
572
+ Choice("Config bundle", "config-bundle", "Compare two configuration bundle versions"),
573
+ Choice("Target based", "target-based", "Compare two gateway-target runtime endpoints"),
574
+ ],
575
+ )
576
+ gateway = interactive.select("Select gateway", [Choice(g, g) for g in resources["gateways"]])
577
+ control_v = _variant("Control", mode, resources, 50)
578
+ treatment_v = _variant("Treatment", mode, resources, 100 - (control_v["weight"] or 50))
579
+ treatment_weight = treatment_v["weight"] or 0
580
+ control_weight = 100 - treatment_weight
581
+ online_eval = None
582
+ if mode == "config-bundle":
583
+ online_eval = interactive.select(
584
+ "Shared online eval config", [Choice(c, c) for c in resources["onlineEvalConfigs"]]
585
+ )
586
+ typer.echo("Gateway filter (optional)")
587
+ typer.echo('Restrict the test to one gateway target path pattern (e.g. "/orders/*").')
588
+ typer.echo("Leave blank to have no gateway filter.")
589
+ gateway_filter = interactive.text("Gateway filter").strip()
590
+ typer.echo("A short name for this A/B test.")
591
+ name = interactive.text("A/B test name", validate=lambda v: None if v.strip() else "Name is required").strip()
592
+
593
+ rows = [("Name", name), ("Mode", mode), ("Gateway", gateway)]
594
+ if mode == "config-bundle":
595
+ rows += [
596
+ ("Control", f"{control_v['bundle']} @ {control_v['version']} (weight {control_weight})"),
597
+ ("Treatment", f"{treatment_v['bundle']} @ {treatment_v['version']} (weight {treatment_weight})"),
598
+ ("Online eval", online_eval or ""),
599
+ ]
600
+ else:
601
+ rows += [
602
+ ("Control", f"{control_v['target']} — eval: {control_v['eval']} (weight {control_weight})"),
603
+ ("Treatment", f"{treatment_v['target']} — eval: {treatment_v['eval']} (weight {treatment_weight})"),
604
+ ]
605
+ rows.append(("Gateway filter", gateway_filter or "none"))
606
+ for label, value in rows:
607
+ typer.echo(f" {label}: {value}")
608
+ if not interactive.confirm("Start A/B test?", default=True):
609
+ typer.echo("Cancelled.")
610
+ return
611
+ cb = mode == "config-bundle"
612
+ engine = create_job_engine(ConfigIO())
613
+ result = engine.start(
614
+ "ab-test",
615
+ {
616
+ "name": name,
617
+ "mode": mode,
618
+ "gateway": gateway,
619
+ "controlBundle": control_v.get("bundle") if cb else None,
620
+ "controlVersion": control_v.get("version") if cb else None,
621
+ "treatmentBundle": treatment_v.get("bundle") if cb else None,
622
+ "treatmentVersion": treatment_v.get("version") if cb else None,
623
+ "controlTarget": None if cb else control_v.get("target"),
624
+ "treatmentTarget": None if cb else treatment_v.get("target"),
625
+ "onlineEval": online_eval if cb else None,
626
+ "controlOnlineEval": None if cb else control_v.get("eval"),
627
+ "treatmentOnlineEval": None if cb else treatment_v.get("eval"),
628
+ "gatewayFilter": gateway_filter or None,
629
+ "controlWeight": control_weight,
630
+ "treatmentWeight": treatment_weight,
631
+ "enableOnCreate": True,
632
+ "onProgress": lambda _s, m: typer.echo(m),
633
+ },
634
+ )
635
+ if not result.success:
636
+ _error("A/B test failed", str(result.error))
637
+ record = result.value
638
+ typer.secho(f"✓ {record['id']} ({record['status']})", fg=typer.colors.GREEN)
639
+ typer.echo(f"Next: agentcore view ab-test {record['id']}")