testdriverai 7.3.2 → 7.3.3

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 (359) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +4 -0
  3. package/.github/workflows/acceptance-linux-scheduled.yaml +45 -0
  4. package/.github/workflows/acceptance-windows-scheduled.yaml +54 -0
  5. package/.github/workflows/acceptance.yaml +106 -0
  6. package/.github/workflows/publish.yaml +75 -0
  7. package/.github/workflows/test-init.yml +157 -0
  8. package/.github/workflows/testdriver.yml +170 -0
  9. package/.github/workflows/windows-self-hosted.yaml +82 -0
  10. package/.prettierignore +4 -0
  11. package/.prettierrc +1 -0
  12. package/CHANGELOG.md +158 -0
  13. package/SKILLs.md +17 -0
  14. package/ai/.claude-plugin/plugin.json +9 -0
  15. package/docs/GITHUB_COMMENTS.md +330 -0
  16. package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
  17. package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
  18. package/docs/TEST-GITHUB-COMMENTS.md +129 -0
  19. package/docs/_scripts/generate-skills.js +149 -0
  20. package/docs/_scripts/link-replacer.js +164 -0
  21. package/docs/_scripts/upload-docs-to-openai.js +284 -0
  22. package/docs/claude-mcp-plugin.mdx +160 -0
  23. package/docs/docs.json +394 -0
  24. package/docs/github-integration-setup.md +266 -0
  25. package/docs/guide/best-practices-polling.mdx +154 -0
  26. package/docs/images/content/account/newprojectsettings.png +0 -0
  27. package/docs/images/content/account/projectpage.png +0 -0
  28. package/docs/images/content/account/projectreplays.png +0 -0
  29. package/docs/images/content/account/team-manage.png +0 -0
  30. package/docs/images/content/account/teampage.png +0 -0
  31. package/docs/images/content/extension/cursor.svg +1 -0
  32. package/docs/images/content/extension/vscode.svg +57 -0
  33. package/docs/images/content/extension/windsurf.svg +3 -0
  34. package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
  35. package/docs/images/content/side-by-side.png +0 -0
  36. package/docs/images/content/vscode/ide-full.png +0 -0
  37. package/docs/images/content/vscode/running.png +0 -0
  38. package/docs/images/content/vscode/vscode-2-assert.png +0 -0
  39. package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
  40. package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
  41. package/docs/images/content/vscode/vscode-file-creation.png +0 -0
  42. package/docs/images/content/vscode/vscode-install.png +0 -0
  43. package/docs/images/content/vscode/vscode-overview.png +0 -0
  44. package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
  45. package/docs/images/content/vscode/vscode-stopchat.png +0 -0
  46. package/docs/images/content/vscode/vscode-stoptest.png +0 -0
  47. package/docs/images/content/vscode/vscode-tdservice.png +0 -0
  48. package/docs/images/content/vscode/vscode-test-output.png +0 -0
  49. package/docs/images/content/vscode/vscode-testhistory.png +0 -0
  50. package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
  51. package/docs/images/content/vscode/vscode-testpane.png +0 -0
  52. package/docs/images/template/dark.png +0 -0
  53. package/docs/images/template/icon.png +0 -0
  54. package/docs/images/template/light.png +0 -0
  55. package/docs/snippets/calendar-link.mdx +4 -0
  56. package/docs/snippets/gitignore-warning.mdx +7 -0
  57. package/docs/snippets/lifecycle-warning.mdx +6 -0
  58. package/docs/snippets/test-prereqs.mdx +12 -0
  59. package/docs/snippets/tests/assert-replay.mdx +7 -0
  60. package/docs/snippets/tests/assert-yaml.mdx +8 -0
  61. package/docs/snippets/tests/exec-js-replay.mdx +7 -0
  62. package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
  63. package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
  64. package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
  65. package/docs/snippets/tests/hover-image-replay.mdx +7 -0
  66. package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
  67. package/docs/snippets/tests/hover-text-replay.mdx +7 -0
  68. package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
  69. package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
  70. package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
  71. package/docs/snippets/tests/match-image-replay.mdx +7 -0
  72. package/docs/snippets/tests/match-image-yaml.mdx +17 -0
  73. package/docs/snippets/tests/press-keys-replay.mdx +7 -0
  74. package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
  75. package/docs/snippets/tests/remember-replay.mdx +7 -0
  76. package/docs/snippets/tests/remember-yaml.mdx +28 -0
  77. package/docs/snippets/tests/scroll-replay.mdx +7 -0
  78. package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
  79. package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
  80. package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
  81. package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
  82. package/docs/snippets/tests/scroll-yaml.mdx +30 -0
  83. package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
  84. package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
  85. package/docs/snippets/tests/type-replay.mdx +7 -0
  86. package/docs/snippets/tests/type-yaml.mdx +28 -0
  87. package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
  88. package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
  89. package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
  90. package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
  91. package/docs/snippets/tests/wait-replay.mdx +7 -0
  92. package/docs/snippets/tests/wait-yaml.mdx +13 -0
  93. package/docs/styles.css +65 -0
  94. package/docs/v6/account/dashboard.mdx +16 -0
  95. package/docs/v6/account/enterprise.mdx +110 -0
  96. package/docs/v6/account/pricing.mdx +33 -0
  97. package/docs/v6/account/projects.mdx +33 -0
  98. package/docs/v6/account/team.mdx +35 -0
  99. package/docs/v6/action/ami.mdx +109 -0
  100. package/docs/v6/action/performance.mdx +105 -0
  101. package/docs/v6/action/secrets.mdx +93 -0
  102. package/docs/v6/apps/chrome-extensions.mdx +48 -0
  103. package/docs/v6/apps/desktop-apps.mdx +93 -0
  104. package/docs/v6/apps/mobile-apps.mdx +26 -0
  105. package/docs/v6/apps/static-websites.mdx +54 -0
  106. package/docs/v6/apps/tauri-apps.mdx +361 -0
  107. package/docs/v6/bugs/jira.mdx +232 -0
  108. package/docs/v6/cli/overview.mdx +66 -0
  109. package/docs/v6/commands/assert.mdx +45 -0
  110. package/docs/v6/commands/exec.mdx +282 -0
  111. package/docs/v6/commands/focus-application.mdx +44 -0
  112. package/docs/v6/commands/hover-image.mdx +69 -0
  113. package/docs/v6/commands/hover-text.mdx +47 -0
  114. package/docs/v6/commands/if.mdx +53 -0
  115. package/docs/v6/commands/match-image.mdx +67 -0
  116. package/docs/v6/commands/press-keys.mdx +87 -0
  117. package/docs/v6/commands/remember.mdx +49 -0
  118. package/docs/v6/commands/run.mdx +44 -0
  119. package/docs/v6/commands/scroll-until-image.mdx +66 -0
  120. package/docs/v6/commands/scroll-until-text.mdx +60 -0
  121. package/docs/v6/commands/scroll.mdx +69 -0
  122. package/docs/v6/commands/type.mdx +45 -0
  123. package/docs/v6/commands/wait-for-image.mdx +54 -0
  124. package/docs/v6/commands/wait-for-text.mdx +48 -0
  125. package/docs/v6/commands/wait.mdx +45 -0
  126. package/docs/v6/exporting/junit.mdx +218 -0
  127. package/docs/v6/exporting/playwright.mdx +197 -0
  128. package/docs/v6/features/auto-healing.mdx +144 -0
  129. package/docs/v6/features/generation.mdx +116 -0
  130. package/docs/v6/features/parallel-testing.mdx +151 -0
  131. package/docs/v6/features/reusable-snippets.mdx +131 -0
  132. package/docs/v6/features/selectorless.mdx +80 -0
  133. package/docs/v6/features/visual-assertions.mdx +139 -0
  134. package/docs/v6/getting-started/ci.mdx +146 -0
  135. package/docs/v6/getting-started/cli.mdx +91 -0
  136. package/docs/v6/getting-started/editing.mdx +100 -0
  137. package/docs/v6/getting-started/playwright.mdx +342 -0
  138. package/docs/v6/getting-started/running.mdx +48 -0
  139. package/docs/v6/getting-started/self-hosting.mdx +408 -0
  140. package/docs/v6/getting-started/vscode.mdx +88 -0
  141. package/docs/v6/guide/assertions.mdx +189 -0
  142. package/docs/v6/guide/authentication.mdx +136 -0
  143. package/docs/v6/guide/code.mdx +65 -0
  144. package/docs/v6/guide/dashcam.mdx +118 -0
  145. package/docs/v6/guide/environment-variables.mdx +26 -0
  146. package/docs/v6/guide/lifecycle.mdx +242 -0
  147. package/docs/v6/guide/locating.mdx +141 -0
  148. package/docs/v6/guide/protips.mdx +43 -0
  149. package/docs/v6/guide/variables.mdx +143 -0
  150. package/docs/v6/guide/waiting.mdx +130 -0
  151. package/docs/v6/importing/csv.mdx +196 -0
  152. package/docs/v6/importing/gherkin.mdx +143 -0
  153. package/docs/v6/importing/jira.mdx +164 -0
  154. package/docs/v6/importing/testrail.mdx +162 -0
  155. package/docs/v6/integrations/electron.mdx +146 -0
  156. package/docs/v6/integrations/netlify.mdx +100 -0
  157. package/docs/v6/integrations/vercel.mdx +125 -0
  158. package/docs/v6/interactive/explore.mdx +99 -0
  159. package/docs/v6/interactive/run.mdx +52 -0
  160. package/docs/v6/interactive/save.mdx +63 -0
  161. package/docs/v6/overview/comparison.mdx +101 -0
  162. package/docs/v6/overview/faq.mdx +162 -0
  163. package/docs/v6/overview/performance.mdx +52 -0
  164. package/docs/v6/overview/quickstart.mdx +137 -0
  165. package/docs/v6/overview/what-is-testdriver.mdx +85 -0
  166. package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
  167. package/docs/v6/scenarios/cookie-banner.mdx +32 -0
  168. package/docs/v6/scenarios/file-upload.mdx +33 -0
  169. package/docs/v6/scenarios/form-filling.mdx +32 -0
  170. package/docs/v6/scenarios/log-in.mdx +75 -0
  171. package/docs/v6/scenarios/pdf-generation.mdx +25 -0
  172. package/docs/v6/scenarios/spell-check.mdx +22 -0
  173. package/docs/v6/security/action.mdx +84 -0
  174. package/docs/v6/security/agent.mdx +73 -0
  175. package/docs/v6/security/platform.mdx +77 -0
  176. package/docs/v6/tutorials/advanced-test.mdx +81 -0
  177. package/docs/v6/tutorials/basic-test.mdx +45 -0
  178. package/docs/v7/_drafts/agents.mdx +852 -0
  179. package/docs/v7/_drafts/architecture.mdx +399 -0
  180. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  181. package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
  182. package/docs/v7/_drafts/best-practices.mdx +486 -0
  183. package/docs/v7/_drafts/caching-ai.mdx +215 -0
  184. package/docs/v7/_drafts/caching-selectors.mdx +424 -0
  185. package/docs/v7/_drafts/caching.mdx +366 -0
  186. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
  187. package/docs/v7/_drafts/commands/assert.mdx +45 -0
  188. package/docs/v7/_drafts/commands/exec.mdx +282 -0
  189. package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
  190. package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
  191. package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
  192. package/docs/v7/_drafts/commands/if.mdx +53 -0
  193. package/docs/v7/_drafts/commands/match-image.mdx +67 -0
  194. package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
  195. package/docs/v7/_drafts/commands/remember.mdx +49 -0
  196. package/docs/v7/_drafts/commands/run.mdx +44 -0
  197. package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
  198. package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
  199. package/docs/v7/_drafts/commands/scroll.mdx +69 -0
  200. package/docs/v7/_drafts/commands/type.mdx +45 -0
  201. package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
  202. package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
  203. package/docs/v7/_drafts/commands/wait.mdx +45 -0
  204. package/docs/v7/_drafts/configuration.mdx +378 -0
  205. package/docs/v7/_drafts/contributing.mdx +174 -0
  206. package/docs/v7/_drafts/core.mdx +458 -0
  207. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  208. package/docs/v7/_drafts/debugging.mdx +349 -0
  209. package/docs/v7/_drafts/error-handling.mdx +501 -0
  210. package/docs/v7/_drafts/faq.mdx +393 -0
  211. package/docs/v7/_drafts/hooks.mdx +360 -0
  212. package/docs/v7/_drafts/init-command.mdx +95 -0
  213. package/docs/v7/_drafts/installation.mdx +420 -0
  214. package/docs/v7/_drafts/migration.mdx +562 -0
  215. package/docs/v7/_drafts/observable.mdx +604 -0
  216. package/docs/v7/_drafts/playwright.mdx +342 -0
  217. package/docs/v7/_drafts/plugin-migration.mdx +220 -0
  218. package/docs/v7/_drafts/powerful.mdx +419 -0
  219. package/docs/v7/_drafts/presets.mdx +210 -0
  220. package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
  221. package/docs/v7/_drafts/prompt-cache.mdx +200 -0
  222. package/docs/v7/_drafts/provision.mdx +390 -0
  223. package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
  224. package/docs/v7/_drafts/readme.mdx +135 -0
  225. package/docs/v7/_drafts/reports.mdx +414 -0
  226. package/docs/v7/_drafts/scalable.mdx +754 -0
  227. package/docs/v7/_drafts/screenshot.mdx +155 -0
  228. package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
  229. package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
  230. package/docs/v7/_drafts/sdk-migration.mdx +474 -0
  231. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  232. package/docs/v7/_drafts/self-hosting.mdx +369 -0
  233. package/docs/v7/_drafts/test-recording.mdx +382 -0
  234. package/docs/v7/_drafts/troubleshooting.mdx +526 -0
  235. package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
  236. package/docs/v7/_drafts/vitest.mdx +535 -0
  237. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  238. package/{ai/skills/testdriver:ai/SKILL.md → docs/v7/ai.mdx} +4 -3
  239. package/{ai/skills/testdriver:assert/SKILL.md → docs/v7/assert.mdx} +4 -3
  240. package/{ai/skills/testdriver:aws-setup/SKILL.md → docs/v7/aws-setup.mdx} +4 -3
  241. package/{ai/skills/testdriver:caching/SKILL.md → docs/v7/caching.mdx} +7 -3
  242. package/{ai/skills/testdriver:captcha/SKILL.md → docs/v7/captcha.mdx} +4 -3
  243. package/{ai/skills/testdriver:ci-cd/SKILL.md → docs/v7/ci-cd.mdx} +4 -3
  244. package/{ai/skills/testdriver:click/SKILL.md → docs/v7/click.mdx} +4 -3
  245. package/{ai/skills/testdriver:client/SKILL.md → docs/v7/client.mdx} +8 -3
  246. package/{ai/skills/testdriver:cloud/SKILL.md → docs/v7/cloud.mdx} +4 -3
  247. package/{ai/skills/testdriver:customizing-devices/SKILL.md → docs/v7/customizing-devices.mdx} +3 -3
  248. package/{ai/skills/testdriver:dashcam/SKILL.md → docs/v7/dashcam.mdx} +4 -3
  249. package/docs/v7/debugging-with-screenshots.mdx +402 -0
  250. package/{ai/skills/testdriver:device-config/SKILL.md → docs/v7/device-config.mdx} +3 -3
  251. package/{ai/skills/testdriver:double-click/SKILL.md → docs/v7/double-click.mdx} +3 -3
  252. package/{ai/skills/testdriver:elements/SKILL.md → docs/v7/elements.mdx} +4 -3
  253. package/{ai/skills/testdriver:enterprise/SKILL.md → docs/v7/enterprise.mdx} +5 -3
  254. package/docs/v7/examples.mdx +5 -0
  255. package/{ai/skills/testdriver:exec/SKILL.md → docs/v7/exec.mdx} +4 -3
  256. package/{ai/skills/testdriver:find/SKILL.md → docs/v7/find.mdx} +4 -3
  257. package/{ai/skills/testdriver:focus-application/SKILL.md → docs/v7/focus-application.mdx} +4 -3
  258. package/{ai/skills/testdriver:generating-tests/SKILL.md → docs/v7/generating-tests.mdx} +3 -3
  259. package/{ai/skills/testdriver:hover/SKILL.md → docs/v7/hover.mdx} +4 -3
  260. package/{ai/skills/testdriver:locating-elements/SKILL.md → docs/v7/locating-elements.mdx} +3 -3
  261. package/{ai/skills/testdriver:making-assertions/SKILL.md → docs/v7/making-assertions.mdx} +3 -3
  262. package/{ai/skills/testdriver:mouse-down/SKILL.md → docs/v7/mouse-down.mdx} +3 -3
  263. package/{ai/skills/testdriver:mouse-up/SKILL.md → docs/v7/mouse-up.mdx} +3 -3
  264. package/docs/v7/ocr.mdx +236 -0
  265. package/{ai/skills/testdriver:performing-actions/SKILL.md → docs/v7/performing-actions.mdx} +3 -3
  266. package/{ai/skills/testdriver:press-keys/SKILL.md → docs/v7/press-keys.mdx} +4 -3
  267. package/{ai/skills/testdriver:quickstart/SKILL.md → docs/v7/quickstart.mdx} +6 -20
  268. package/{ai/skills/testdriver:reusable-code/SKILL.md → docs/v7/reusable-code.mdx} +3 -3
  269. package/{ai/skills/testdriver:right-click/SKILL.md → docs/v7/right-click.mdx} +3 -3
  270. package/{ai/skills/testdriver:running-tests/SKILL.md → docs/v7/running-tests.mdx} +7 -3
  271. package/{ai/skills/testdriver:screenshot/SKILL.md → docs/v7/screenshot.mdx} +88 -6
  272. package/{ai/skills/testdriver:scroll/SKILL.md → docs/v7/scroll.mdx} +40 -3
  273. package/{ai/skills/testdriver:secrets/SKILL.md → docs/v7/secrets.mdx} +3 -3
  274. package/{ai/skills/testdriver:self-hosted/SKILL.md → docs/v7/self-hosted.mdx} +4 -3
  275. package/{ai/skills/testdriver:type/SKILL.md → docs/v7/type.mdx} +4 -3
  276. package/{ai/skills/testdriver:variables/SKILL.md → docs/v7/variables.mdx} +3 -3
  277. package/{ai/skills/testdriver:waiting-for-elements/SKILL.md → docs/v7/waiting-for-elements.mdx} +3 -3
  278. package/{ai/skills/testdriver:what-is-testdriver/SKILL.md → docs/v7/what-is-testdriver.mdx} +3 -3
  279. package/eslint.config.js +67 -0
  280. package/examples/ai.test.mjs +30 -0
  281. package/examples/assert.test.mjs +47 -0
  282. package/examples/captcha-api.test.mjs +50 -0
  283. package/examples/chrome-extension.test.mjs +94 -0
  284. package/examples/drag-and-drop.test.mjs +58 -0
  285. package/examples/element-not-found.test.mjs +26 -0
  286. package/examples/exec-output.test.mjs +59 -0
  287. package/examples/exec-pwsh.test.mjs +57 -0
  288. package/examples/focus-window.test.mjs +36 -0
  289. package/examples/formatted-logging.test.mjs +26 -0
  290. package/examples/hover-image.test.mjs +52 -0
  291. package/examples/hover-text-with-description.test.mjs +56 -0
  292. package/examples/hover-text.test.mjs +27 -0
  293. package/examples/installer.test.mjs +49 -0
  294. package/examples/launch-vscode-linux.test.mjs +54 -0
  295. package/examples/match-image.test.mjs +54 -0
  296. package/examples/no-provision.test.mjs +23 -0
  297. package/examples/press-keys.test.mjs +50 -0
  298. package/examples/prompt.test.mjs +33 -0
  299. package/examples/scroll-keyboard.test.mjs +37 -0
  300. package/examples/scroll-until-image.test.mjs +39 -0
  301. package/examples/scroll-until-text.test.mjs +67 -0
  302. package/examples/scroll.test.mjs +41 -0
  303. package/examples/type.test.mjs +45 -0
  304. package/examples/windows-installer.test.mjs +53 -0
  305. package/jsconfig.json +26 -0
  306. package/manual/test-init-command.js +223 -0
  307. package/mcp-server/README.md +312 -0
  308. package/mcp-server/mcp-app.html +28 -0
  309. package/mcp-server/mcp-config.example.json +19 -0
  310. package/mcp-server/package-lock.json +4018 -0
  311. package/mcp-server/package.json +29 -0
  312. package/mcp-server/src/codegen.ts +189 -0
  313. package/mcp-server/src/mcp-app.css +360 -0
  314. package/mcp-server/src/mcp-app.ts +547 -0
  315. package/mcp-server/src/provision-types.ts +209 -0
  316. package/mcp-server/src/server.ts +2313 -0
  317. package/mcp-server/src/session.ts +194 -0
  318. package/mcp-server/tsconfig.json +16 -0
  319. package/mcp-server/vite.config.ts +23 -0
  320. package/package.json +2 -17
  321. package/scripts/generate-skills.js +94 -0
  322. package/setup/aws/cloudformation.yaml +470 -0
  323. package/setup/aws/spawn-runner.sh +190 -0
  324. package/test/api-resilience.test.mjs +0 -0
  325. package/test/captcha-solver.test.mjs +152 -0
  326. package/test/chrome-remote-debugging.test.mjs +66 -0
  327. package/test/duckduckgo/experiment.test.mjs +28 -0
  328. package/test/duckduckgo/setup.test.mjs +29 -0
  329. package/test/manual/debug-locate-response.js +82 -0
  330. package/test/manual/reconnect-provision.test.mjs +49 -0
  331. package/test/manual/test-console-logs.test.mjs +42 -0
  332. package/test/manual/test-find-api.js +73 -0
  333. package/test/manual/test-init.sh +54 -0
  334. package/test/manual/test-prompt-cache.js +97 -0
  335. package/test/manual/test-provision-auth.mjs +22 -0
  336. package/test/manual/test-sandbox-render.js +29 -0
  337. package/test/manual/test-sdk-methods.js +15 -0
  338. package/test/manual/test-sdk-refactor.js +53 -0
  339. package/test/manual/test-stack-trace.mjs +57 -0
  340. package/test/manual/verify-element-api.js +89 -0
  341. package/test/manual/verify-types.js +0 -0
  342. package/test/manual-unawaited-promise.test.mjs +31 -0
  343. package/test-ide-preview.mjs +17 -0
  344. package/tests/airbnb-booking.test.mjs +39 -0
  345. package/tests/airbnb-search.test.mjs +43 -0
  346. package/tests/example.test.js +33 -0
  347. package/tests/login.js +28 -0
  348. package/vitest.config.mjs +24 -0
  349. package/vscode-extension/.vscodeignore +12 -0
  350. package/vscode-extension/README.md +94 -0
  351. package/vscode-extension/media/icon.png +0 -0
  352. package/vscode-extension/package-lock.json +4126 -0
  353. package/vscode-extension/package.json +86 -0
  354. package/vscode-extension/src/extension.ts +829 -0
  355. package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
  356. package/vscode-extension/tsconfig.json +16 -0
  357. package/ai/skills/testdriver:examples/SKILL.md +0 -7
  358. package/ai/skills/testdriver:mcp-workflow/SKILL.md +0 -410
  359. package/ai/skills/testdriver:testdriver/SKILL.md +0 -523
@@ -0,0 +1,470 @@
1
+ AWSTemplateFormatVersion: "2010-09-09"
2
+ Description: >-
3
+ Baseline artifacts (NO EC2 instance): Creates a dedicated VPC with public subnet, Security Group,
4
+ IAM Role/Profile, optional KeyPair, and an EC2 Launch Template so you can spawn many instances
5
+ programmatically. Writes handy IDs into SSM Parameter Store for easy lookup in scripts or automation.
6
+
7
+ Metadata:
8
+ AWS::CloudFormation::Interface:
9
+ ParameterGroups:
10
+ - Label:
11
+ default: "Notification Configuration"
12
+ Parameters:
13
+ - NotificationEmail
14
+ - Label:
15
+ default: "Project Configuration"
16
+ Parameters:
17
+ - ProjectTag
18
+ - Label:
19
+ default: "Network Configuration"
20
+ Parameters:
21
+ - AllowedIngressCidr
22
+ - Label:
23
+ default: "Instance Configuration"
24
+ Parameters:
25
+ - InstanceType
26
+ - Label:
27
+ default: "Key Pair Configuration"
28
+ Parameters:
29
+ - CreateKeyPair
30
+ - ExistingKeyName
31
+ ParameterLabels:
32
+ ProjectTag:
33
+ default: "Project Tag"
34
+ InstanceType:
35
+ default: "Instance Type"
36
+ AllowedIngressCidr:
37
+ default: "Allowed Ingress CIDR"
38
+ CreateKeyPair:
39
+ default: "Create New Key Pair"
40
+ ExistingKeyName:
41
+ default: "Existing Key Name (only required if 'Create New Key Pair' is 'no')"
42
+ NotificationEmail:
43
+ default: "Notification Email (optional)"
44
+
45
+ Rules:
46
+ ValidateKeyPairConfiguration:
47
+ RuleCondition: !Equals [!Ref CreateKeyPair, "no"]
48
+ Assertions:
49
+ - Assert: !Not [!Equals [!Ref ExistingKeyName, ""]]
50
+ AssertDescription: "ExistingKeyName must be provided when CreateKeyPair is 'no'"
51
+
52
+ Parameters:
53
+ NotificationEmail:
54
+ Type: String
55
+ Default: ""
56
+ Description: Email address to receive deployment completion notifications (optional)
57
+
58
+ ProjectTag:
59
+ Type: String
60
+ Default: testdriver
61
+
62
+ InstanceType:
63
+ Type: String
64
+ Default: c5.xlarge
65
+ AllowedValues:
66
+ - c5.xlarge
67
+ - c5.2xlarge
68
+ - c5.4xlarge
69
+ - c5.9xlarge
70
+ - c5.12xlarge
71
+ - c5.18xlarge
72
+ - c5.24xlarge
73
+ - c5.metal
74
+ - i3.metal
75
+ Description: Instance type - only c5.xlarge or larger, plus c5.metal and i3.metal allowed
76
+
77
+ AllowedIngressCidr:
78
+ Type: String
79
+ Default: 0.0.0.0/0
80
+ Description: CIDR allowed to access inbound ports (0.0.0.0/0 means "anyone", we recommend tightening this in production).
81
+
82
+ CreateKeyPair:
83
+ Type: String
84
+ AllowedValues: ["yes", "no"]
85
+ Default: "yes"
86
+ Description: Create a new key pair for instance access? (If 'no', you must provide an existing key name)
87
+ ExistingKeyName:
88
+ Type: String
89
+ Default: ""
90
+ Description: Name of existing EC2 Key Pair (only required when CreateKeyPair is 'no')
91
+
92
+ Conditions:
93
+ UseExistingKeyProvided: !Not [!Equals [!Ref ExistingKeyName, ""]]
94
+ CreateKey: !Equals [!Ref CreateKeyPair, "yes"]
95
+ SendNotification: !Not [!Equals [!Ref NotificationEmail, ""]]
96
+
97
+ Resources:
98
+ # VPC for TestDriver
99
+ TestDriverVpc:
100
+ Type: AWS::EC2::VPC
101
+ Properties:
102
+ CidrBlock: 10.0.0.0/16
103
+ EnableDnsHostnames: true
104
+ EnableDnsSupport: true
105
+ Tags:
106
+ - { Key: Name, Value: !Sub "${AWS::StackName}-vpc" }
107
+ - { Key: Project, Value: !Ref ProjectTag }
108
+
109
+ # Public subnet for EC2 instances
110
+ PublicSubnet:
111
+ Type: AWS::EC2::Subnet
112
+ Properties:
113
+ VpcId: !Ref TestDriverVpc
114
+ CidrBlock: 10.0.1.0/24
115
+ AvailabilityZone: !Select [0, !GetAZs ""]
116
+ MapPublicIpOnLaunch: true
117
+ Tags:
118
+ - { Key: Name, Value: !Sub "${AWS::StackName}-public-subnet" }
119
+ - { Key: Project, Value: !Ref ProjectTag }
120
+
121
+ # Internet Gateway
122
+ InternetGateway:
123
+ Type: AWS::EC2::InternetGateway
124
+ Properties:
125
+ Tags:
126
+ - { Key: Name, Value: !Sub "${AWS::StackName}-igw" }
127
+ - { Key: Project, Value: !Ref ProjectTag }
128
+
129
+ # Attach Internet Gateway to VPC
130
+ AttachGateway:
131
+ Type: AWS::EC2::VPCGatewayAttachment
132
+ Properties:
133
+ VpcId: !Ref TestDriverVpc
134
+ InternetGatewayId: !Ref InternetGateway
135
+
136
+ # Route table for public subnet
137
+ PublicRouteTable:
138
+ Type: AWS::EC2::RouteTable
139
+ Properties:
140
+ VpcId: !Ref TestDriverVpc
141
+ Tags:
142
+ - { Key: Name, Value: !Sub "${AWS::StackName}-public-rt" }
143
+ - { Key: Project, Value: !Ref ProjectTag }
144
+
145
+ # Route to Internet Gateway
146
+ PublicRoute:
147
+ Type: AWS::EC2::Route
148
+ DependsOn: AttachGateway
149
+ Properties:
150
+ RouteTableId: !Ref PublicRouteTable
151
+ DestinationCidrBlock: 0.0.0.0/0
152
+ GatewayId: !Ref InternetGateway
153
+
154
+ # Associate route table with public subnet
155
+ SubnetRouteTableAssociation:
156
+ Type: AWS::EC2::SubnetRouteTableAssociation
157
+ Properties:
158
+ SubnetId: !Ref PublicSubnet
159
+ RouteTableId: !Ref PublicRouteTable
160
+
161
+ SecurityGroup:
162
+ Type: AWS::EC2::SecurityGroup
163
+ Properties:
164
+ GroupDescription: SG for QA desktop testing (RDP/HTTPS/NGINX/pyautogui + VNC)
165
+ VpcId: !Ref TestDriverVpc
166
+ SecurityGroupIngress:
167
+ - {
168
+ IpProtocol: tcp,
169
+ FromPort: 8765,
170
+ ToPort: 8765,
171
+ CidrIp: !Ref AllowedIngressCidr,
172
+ Description: "pyautogui-cli WebSockets"
173
+ }
174
+ - {
175
+ IpProtocol: tcp,
176
+ FromPort: 5800,
177
+ ToPort: 5800,
178
+ CidrIp: !Ref AllowedIngressCidr,
179
+ Description: "WebVNC 5800",
180
+ }
181
+ - {
182
+ IpProtocol: tcp,
183
+ FromPort: 8443,
184
+ ToPort: 8443,
185
+ CidrIp: !Ref AllowedIngressCidr,
186
+ Description: "Custom 8443",
187
+ }
188
+ - {
189
+ IpProtocol: tcp,
190
+ FromPort: 8080,
191
+ ToPort: 8080,
192
+ CidrIp: !Ref AllowedIngressCidr,
193
+ Description: "NGINX 8080",
194
+ }
195
+ - {
196
+ IpProtocol: tcp,
197
+ FromPort: 80,
198
+ ToPort: 80,
199
+ CidrIp: !Ref AllowedIngressCidr,
200
+ Description: "HTTP 80",
201
+ }
202
+ - {
203
+ IpProtocol: tcp,
204
+ FromPort: 443,
205
+ ToPort: 443,
206
+ CidrIp: !Ref AllowedIngressCidr,
207
+ Description: "HTTPS 443",
208
+ }
209
+ - {
210
+ IpProtocol: tcp,
211
+ FromPort: 3389,
212
+ ToPort: 3389,
213
+ CidrIp: !Ref AllowedIngressCidr,
214
+ Description: "RDP 3389",
215
+ }
216
+ - {
217
+ IpProtocol: tcp,
218
+ FromPort: 5900,
219
+ ToPort: 5900,
220
+ CidrIp: !Ref AllowedIngressCidr,
221
+ Description: "TightVNC 5900",
222
+ }
223
+ - {
224
+ IpProtocol: tcp,
225
+ FromPort: 5901,
226
+ ToPort: 5901,
227
+ CidrIp: !Ref AllowedIngressCidr,
228
+ Description: "noVNC Websockify 5901",
229
+ }
230
+ - {
231
+ IpProtocol: tcp,
232
+ FromPort: 6080,
233
+ ToPort: 6080,
234
+ CidrIp: !Ref AllowedIngressCidr,
235
+ Description: "noVNC HTTP 6080",
236
+ }
237
+ SecurityGroupEgress:
238
+ - IpProtocol: -1
239
+ CidrIp: 0.0.0.0/0
240
+ Description: Allow all outbound
241
+ Tags:
242
+ - { Key: Project, Value: !Ref ProjectTag }
243
+
244
+ InstanceRole:
245
+ Type: AWS::IAM::Role
246
+ Properties:
247
+ AssumeRolePolicyDocument:
248
+ Version: "2012-10-17"
249
+ Statement:
250
+ - Effect: Allow
251
+ Principal: { Service: ec2.amazonaws.com }
252
+ Action: sts:AssumeRole
253
+ ManagedPolicyArns:
254
+ - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
255
+ Tags:
256
+ - { Key: Project, Value: !Ref ProjectTag }
257
+
258
+ InstanceProfile:
259
+ Type: AWS::IAM::InstanceProfile
260
+ Properties:
261
+ Roles: [!Ref InstanceRole]
262
+
263
+ KeyPair:
264
+ Type: AWS::EC2::KeyPair
265
+ Condition: CreateKey
266
+ Properties:
267
+ KeyName: !Sub "${AWS::StackName}-key"
268
+ KeyType: rsa
269
+
270
+ LaunchTemplate:
271
+ Type: AWS::EC2::LaunchTemplate
272
+ Properties:
273
+ LaunchTemplateName: !Sub "${AWS::StackName}-lt"
274
+ LaunchTemplateData:
275
+ InstanceType: !Ref InstanceType
276
+ IamInstanceProfile:
277
+ Name: !Ref InstanceProfile
278
+ # Lock SG + Subnet to the same VPC
279
+ NetworkInterfaces:
280
+ - DeviceIndex: 0
281
+ SubnetId: !Ref PublicSubnet
282
+ Groups: [!Ref SecurityGroup]
283
+ AssociatePublicIpAddress: true
284
+ KeyName: !If
285
+ - CreateKey
286
+ - !Ref KeyPair
287
+ - !If
288
+ - UseExistingKeyProvided
289
+ - !Ref ExistingKeyName
290
+ - !Ref AWS::NoValue
291
+ TagSpecifications:
292
+ - ResourceType: instance
293
+ Tags: [{ Key: Project, Value: !Ref ProjectTag }]
294
+ - ResourceType: volume
295
+ Tags: [{ Key: Project, Value: !Ref ProjectTag }]
296
+
297
+ # SNS Topic for deployment notifications
298
+ DeploymentNotificationTopic:
299
+ Type: AWS::SNS::Topic
300
+ Condition: SendNotification
301
+ Properties:
302
+ TopicName: !Sub "${AWS::StackName}-deployment-notifications"
303
+ DisplayName: !Sub "${AWS::StackName} Deployment Notifications"
304
+ Tags:
305
+ - { Key: Project, Value: !Ref ProjectTag }
306
+
307
+ # SNS Subscription for email notifications
308
+ EmailSubscription:
309
+ Type: AWS::SNS::Subscription
310
+ Condition: SendNotification
311
+ Properties:
312
+ Protocol: email
313
+ TopicArn: !Ref DeploymentNotificationTopic
314
+ Endpoint: !Ref NotificationEmail
315
+
316
+ # Custom resource to send completion notification
317
+ DeploymentCompleteNotification:
318
+ Type: AWS::CloudFormation::CustomResource
319
+ Condition: SendNotification
320
+ Properties:
321
+ ServiceToken: !GetAtt NotificationLambda.Arn
322
+ StackName: !Ref AWS::StackName
323
+ TopicArn: !Ref DeploymentNotificationTopic
324
+ DependsOn:
325
+ - SsmParamSg
326
+ - SsmParamIp
327
+ - SsmParamLt
328
+ - SsmParamLtLatest
329
+ - SsmParamVpc
330
+ - SsmParamSubnet
331
+
332
+ # Lambda function to send the notification
333
+ NotificationLambda:
334
+ Type: AWS::Lambda::Function
335
+ Condition: SendNotification
336
+ Properties:
337
+ FunctionName: !Sub "${AWS::StackName}-deployment-notifier"
338
+ Runtime: python3.11
339
+ Handler: index.lambda_handler
340
+ Role: !GetAtt NotificationLambdaRole.Arn
341
+ Code:
342
+ ZipFile: |
343
+ import boto3
344
+ import json
345
+ import cfnresponse
346
+
347
+ def lambda_handler(event, context):
348
+ try:
349
+ if event['RequestType'] == 'Create':
350
+ sns = boto3.client('sns')
351
+ stack_name = event['ResourceProperties']['StackName']
352
+ topic_arn = event['ResourceProperties']['TopicArn']
353
+
354
+ message = f"""
355
+ TestDriver Infrastructure Deployment Complete!
356
+
357
+ Stack Name: {stack_name}
358
+ Status: CREATE_COMPLETE
359
+
360
+ Your TestDriver infrastructure is now ready to use.
361
+ Check the CloudFormation outputs for resource IDs and configuration details.
362
+ """
363
+
364
+ sns.publish(
365
+ TopicArn=topic_arn,
366
+ Subject=f'TestDriver Stack {stack_name} - Deployment Complete',
367
+ Message=message
368
+ )
369
+
370
+ cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
371
+ except Exception as e:
372
+ print(f"Error: {e}")
373
+ cfnresponse.send(event, context, cfnresponse.FAILED, {})
374
+ Tags:
375
+ - { Key: Project, Value: !Ref ProjectTag }
376
+
377
+ # IAM Role for the notification Lambda
378
+ NotificationLambdaRole:
379
+ Type: AWS::IAM::Role
380
+ Condition: SendNotification
381
+ Properties:
382
+ AssumeRolePolicyDocument:
383
+ Version: "2012-10-17"
384
+ Statement:
385
+ - Effect: Allow
386
+ Principal:
387
+ Service: lambda.amazonaws.com
388
+ Action: sts:AssumeRole
389
+ ManagedPolicyArns:
390
+ - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
391
+ Policies:
392
+ - PolicyName: SNSPublishPolicy
393
+ PolicyDocument:
394
+ Version: "2012-10-17"
395
+ Statement:
396
+ - Effect: Allow
397
+ Action:
398
+ - sns:Publish
399
+ Resource: !Ref DeploymentNotificationTopic
400
+ Tags:
401
+ - { Key: Project, Value: !Ref ProjectTag }
402
+
403
+ SsmParamSg:
404
+ Type: AWS::SSM::Parameter
405
+ Properties:
406
+ Name: !Sub "/testdriver/infra/${AWS::StackName}/security-group-id"
407
+ Type: String
408
+ Value: !Ref SecurityGroup
409
+
410
+ SsmParamIp:
411
+ Type: AWS::SSM::Parameter
412
+ Properties:
413
+ Name: !Sub "/testdriver/infra/${AWS::StackName}/instance-profile-name"
414
+ Type: String
415
+ Value: !Ref InstanceProfile
416
+
417
+ SsmParamLt:
418
+ Type: AWS::SSM::Parameter
419
+ Properties:
420
+ Name: !Sub "/testdriver/infra/${AWS::StackName}/launch-template-id"
421
+ Type: String
422
+ Value: !Ref LaunchTemplate
423
+
424
+ SsmParamLtLatest:
425
+ Type: AWS::SSM::Parameter
426
+ Properties:
427
+ Name: !Sub "/testdriver/infra/${AWS::StackName}/launch-template-latest-version"
428
+ Type: String
429
+ Value: !GetAtt LaunchTemplate.LatestVersionNumber
430
+
431
+ SsmParamVpc:
432
+ Type: AWS::SSM::Parameter
433
+ Properties:
434
+ Name: !Sub "/testdriver/infra/${AWS::StackName}/testdriver-vpc-id"
435
+ Type: String
436
+ Value: !Ref TestDriverVpc
437
+
438
+ SsmParamSubnet:
439
+ Type: AWS::SSM::Parameter
440
+ Properties:
441
+ Name: !Sub "/testdriver/infra/${AWS::StackName}/testdriver-public-subnet-id"
442
+ Type: String
443
+ Value: !Ref PublicSubnet
444
+
445
+ Outputs:
446
+ VpcId:
447
+ Value: !Ref TestDriverVpc
448
+ Description: VPC ID created for TestDriver
449
+ SubnetId:
450
+ Value: !Ref PublicSubnet
451
+ Description: Public subnet ID for TestDriver instances
452
+ SecurityGroupId:
453
+ Value: !Ref SecurityGroup
454
+ Description: Security Group for QA desktop testing
455
+ InstanceProfileName:
456
+ Value: !Ref InstanceProfile
457
+ Description: Instance Profile to attach to instances
458
+ LaunchTemplateId:
459
+ Value: !Ref LaunchTemplate
460
+ Description: EC2 Launch Template ID
461
+ LaunchTemplateLatestVersion:
462
+ Value: !GetAtt LaunchTemplate.LatestVersionNumber
463
+ Description: Latest Launch Template version
464
+ KeyPairSsmParam:
465
+ Condition: CreateKey
466
+ Value: !Sub "/ec2/keypair/${KeyPair.KeyPairId}"
467
+ Description: SSM parameter that stores the generated private key
468
+ SsmNamespaceUsed:
469
+ Value: !Sub "/testdriver/infra/${AWS::StackName}"
470
+ Description: Prefix where IDs are stored for discovery
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # --- Config (reads from env) ---
5
+ : "${AWS_REGION:?Set AWS_REGION}"
6
+ : "${AMI_ID:?Set AMI_ID (TestDriver Ami)}"
7
+ : "${AWS_LAUNCH_TEMPLATE_ID:?Set AWS_LAUNCH_TEMPLATE_ID}"
8
+ : "${AWS_LAUNCH_TEMPLATE_VERSION:=\$Latest}"
9
+ : "${AWS_TAG_PREFIX:=td}"
10
+ : "${RUNNER_CLASS_ID:=default}"
11
+ : "${RESOLUTION:=1440x900}"
12
+
13
+ TAG_NAME="${AWS_TAG_PREFIX}-"$(date +%s)
14
+ WS_CONFIG_PATH='C:\Windows\Temp\pyautogui-ws.json'
15
+
16
+ echo "Launching AWS Instance..."
17
+
18
+ # --- 1) Launch instance ---
19
+ RUN_JSON=$(aws ec2 run-instances \
20
+ --region "$AWS_REGION" \
21
+ --image-id "$AMI_ID" \
22
+ --launch-template "LaunchTemplateId=$AWS_LAUNCH_TEMPLATE_ID,Version=$AWS_LAUNCH_TEMPLATE_VERSION" \
23
+ --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=${TAG_NAME}},{Key=Class,Value=${RUNNER_CLASS_ID}},{Key=TD_RESOLUTION,Value=${RESOLUTION}}]" \
24
+ --output json)
25
+
26
+ INSTANCE_ID=$(jq -r '.Instances[0].InstanceId' <<<"$RUN_JSON")
27
+
28
+ echo "Launched: $INSTANCE_ID"
29
+ echo "Instance details:"
30
+ echo " Region: $AWS_REGION"
31
+ echo " AMI ID: $AMI_ID"
32
+ echo " Launch Template ID: $AWS_LAUNCH_TEMPLATE_ID"
33
+ echo " Launch Template Version: $AWS_LAUNCH_TEMPLATE_VERSION"
34
+
35
+ echo "Waiting for instance to be running..."
36
+
37
+ # --- 2) Wait for running + status checks ---
38
+ aws ec2 wait instance-running --region "$AWS_REGION" --instance-ids "$INSTANCE_ID"
39
+ echo "✓ Instance is now running"
40
+
41
+ echo "Waiting for instance to pass status checks..."
42
+
43
+ aws ec2 wait instance-status-ok --region "$AWS_REGION" --instance-ids "$INSTANCE_ID"
44
+ echo "✓ Instance passed all status checks"
45
+
46
+ # Additional validation - check instance state details
47
+ echo "Validating instance readiness..."
48
+ INSTANCE_STATE=$(aws ec2 describe-instances --region "$AWS_REGION" --instance-ids "$INSTANCE_ID" \
49
+ --query 'Reservations[0].Instances[0].{State:State.Name,StatusChecks:StateTransitionReason}' \
50
+ --output json)
51
+ echo "Instance state details: $INSTANCE_STATE"
52
+
53
+ # --- 3) Ensure SSM connectivity ---
54
+ echo "Waiting for SSM connectivity..."
55
+ echo "This can take several minutes for the SSM agent to be fully ready..."
56
+
57
+ # First, check if the instance is registered with SSM
58
+ echo "Checking SSM instance registration..."
59
+ TRIES=0; MAX_TRIES=60
60
+ while :; do
61
+ echo "Attempt $((TRIES+1))/$MAX_TRIES: Checking if instance is registered with SSM..."
62
+
63
+ # Check if instance appears in SSM managed instances
64
+ if aws ssm describe-instance-information \
65
+ --region "$AWS_REGION" \
66
+ --filters "Key=InstanceIds,Values=$INSTANCE_ID" \
67
+ --query 'InstanceInformationList[0].InstanceId' \
68
+ --output text 2>/dev/null | grep -q "$INSTANCE_ID"; then
69
+ echo "✓ Instance is registered with SSM"
70
+ break
71
+ fi
72
+
73
+ TRIES=$((TRIES+1))
74
+ if [ $TRIES -ge $MAX_TRIES ]; then
75
+ echo "❌ SSM registration timeout - instance may not have proper IAM role or SSM agent"
76
+ echo "Checking instance details for debugging..."
77
+ aws ec2 describe-instances --region "$AWS_REGION" --instance-ids "$INSTANCE_ID" \
78
+ --query 'Reservations[0].Instances[0].{State:State.Name,IAMProfile:IamInstanceProfile.Arn,SecurityGroups:SecurityGroups[].GroupId}' \
79
+ --output table
80
+ exit 2
81
+ fi
82
+ echo "Instance not yet registered with SSM, waiting..."
83
+ sleep 10
84
+ done
85
+
86
+ # Now test SSM command execution
87
+ echo "Testing SSM command execution..."
88
+ TRIES=0; MAX_TRIES=30
89
+ while :; do
90
+ echo "Attempt $((TRIES+1))/$MAX_TRIES: Sending test SSM command..."
91
+
92
+ if CMD_JSON=$(aws ssm send-command \
93
+ --region "$AWS_REGION" \
94
+ --targets "Key=instanceIds,Values=$INSTANCE_ID" \
95
+ --document-name "AWS-RunPowerShellScript" \
96
+ --parameters 'commands=["echo SSM connectivity test successful"]' \
97
+ --output json 2>/dev/null); then
98
+
99
+ COMMAND_ID=$(jq -r '.Command.CommandId' <<<"$CMD_JSON")
100
+ echo "✓ SSM command sent successfully (Command ID: $COMMAND_ID)"
101
+
102
+ # Wait for command to complete and check status
103
+ echo "Waiting for command execution..."
104
+ if aws ssm wait command-executed --region "$AWS_REGION" --command-id "$COMMAND_ID" --instance-id "$INSTANCE_ID" 2>/dev/null; then
105
+ echo "✓ SSM connectivity confirmed"
106
+ break
107
+ else
108
+ echo "⚠ Command execution may have failed, checking status..."
109
+ CMD_STATUS=$(aws ssm get-command-invocation \
110
+ --region "$AWS_REGION" \
111
+ --command-id "$COMMAND_ID" \
112
+ --instance-id "$INSTANCE_ID" \
113
+ --query 'Status' \
114
+ --output text 2>/dev/null || echo "Unknown")
115
+ echo "Command status: $CMD_STATUS"
116
+
117
+ if [ "$CMD_STATUS" = "Success" ]; then
118
+ echo "✓ Command actually succeeded"
119
+ break
120
+ fi
121
+ fi
122
+ else
123
+ echo "⚠ Failed to send SSM command"
124
+ fi
125
+
126
+ TRIES=$((TRIES+1))
127
+ if [ $TRIES -ge $MAX_TRIES ]; then
128
+ echo "❌ SSM command execution timeout"
129
+ echo "Final debugging information:"
130
+
131
+ # Get SSM agent status
132
+ echo "SSM Agent status on instance:"
133
+ aws ssm describe-instance-information \
134
+ --region "$AWS_REGION" \
135
+ --filters "Key=InstanceIds,Values=$INSTANCE_ID" \
136
+ --query 'InstanceInformationList[0].{PingStatus:PingStatus,LastPingDateTime:LastPingDateTime,AgentVersion:AgentVersion}' \
137
+ --output table 2>/dev/null || echo "Could not retrieve SSM status"
138
+
139
+ exit 2
140
+ fi
141
+ echo "Retrying in 20 seconds..."
142
+ sleep 20
143
+ done
144
+
145
+ echo "Getting Public IP..."
146
+
147
+ # # --- 5) Get instance Public IP ---
148
+ DESC_JSON=$(aws ec2 describe-instances --region "$AWS_REGION" --instance-ids "$INSTANCE_ID" --output json)
149
+ PUBLIC_IP=$(jq -r '.Reservations[0].Instances[0].PublicIpAddress // empty' <<<"$DESC_JSON")
150
+ [ -n "$PUBLIC_IP" ] || PUBLIC_IP="No public IP assigned"
151
+
152
+ # echo "Getting Websocket Port..."
153
+
154
+
155
+ # --- 6) Read WebSocket config JSON ---
156
+ echo "Reading WebSocket configuration from: $WS_CONFIG_PATH"
157
+ READ_JSON=$(aws ssm send-command \
158
+ --region "$AWS_REGION" \
159
+ --instance-ids "$INSTANCE_ID" \
160
+ --document-name "AWS-RunPowerShellScript" \
161
+ --parameters "commands=[\"if (Test-Path '${WS_CONFIG_PATH}') { Get-Content -Raw '${WS_CONFIG_PATH}' } else { Write-Output 'Config file not found at ${WS_CONFIG_PATH}' }\"]" \
162
+ --output json)
163
+
164
+ READ_CMD_ID=$(jq -r '.Command.CommandId' <<<"$READ_JSON")
165
+ echo "WebSocket config read command ID: $READ_CMD_ID"
166
+
167
+ echo "Waiting for WebSocket config command to complete..."
168
+ aws ssm wait command-executed --region "$AWS_REGION" --command-id "$READ_CMD_ID" --instance-id "$INSTANCE_ID"
169
+
170
+ INVOC=$(aws ssm get-command-invocation \
171
+ --region "$AWS_REGION" \
172
+ --command-id "$READ_CMD_ID" \
173
+ --instance-id "$INSTANCE_ID" \
174
+ --output json)
175
+
176
+ STDOUT=$(jq -r '.StandardOutputContent // ""' <<<"$INVOC")
177
+ STDERR=$(jq -r '.StandardErrorContent // ""' <<<"$INVOC")
178
+ CMD_STATUS=$(jq -r '.Status // ""' <<<"$INVOC")
179
+
180
+ echo "WebSocket config command status: $CMD_STATUS"
181
+ if [ -n "$STDERR" ] && [ "$STDERR" != "null" ]; then
182
+ echo "WebSocket config stderr: $STDERR"
183
+ fi
184
+ echo "WebSocket config raw output: $STDOUT"
185
+
186
+ # --- 7) Output results ---
187
+ echo "Setup complete!"
188
+ echo "PUBLIC_IP=$PUBLIC_IP"
189
+ echo "INSTANCE_ID=$INSTANCE_ID"
190
+ echo "AWS_REGION=$AWS_REGION"
File without changes