@testdriverai/agent 7.8.0-test.38

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 (528) hide show
  1. package/.claude/settings.local.json +7 -0
  2. package/.env.example +4 -0
  3. package/.prettierignore +4 -0
  4. package/.prettierrc +1 -0
  5. package/CHANGELOG.md +953 -0
  6. package/README.md +81 -0
  7. package/agent/events.js +135 -0
  8. package/agent/index.js +2450 -0
  9. package/agent/interface.js +35 -0
  10. package/agent/lib/analytics.js +22 -0
  11. package/agent/lib/censorship.js +75 -0
  12. package/agent/lib/commander.js +246 -0
  13. package/agent/lib/commands.js +1684 -0
  14. package/agent/lib/config.js +60 -0
  15. package/agent/lib/generator.js +91 -0
  16. package/agent/lib/http.js +144 -0
  17. package/agent/lib/logger.js +56 -0
  18. package/agent/lib/outputs.js +29 -0
  19. package/agent/lib/parser.js +209 -0
  20. package/agent/lib/redraw.js +386 -0
  21. package/agent/lib/resources/cursor-2.png +0 -0
  22. package/agent/lib/sandbox.js +1104 -0
  23. package/agent/lib/sdk.js +633 -0
  24. package/agent/lib/session.js +25 -0
  25. package/agent/lib/source-mapper.js +342 -0
  26. package/agent/lib/subimage/index.js +77 -0
  27. package/agent/lib/subimage/opencv.js +69 -0
  28. package/agent/lib/system.js +204 -0
  29. package/agent/lib/theme.js +14 -0
  30. package/agent/lib/valid-version.js +21 -0
  31. package/agent/lib/validation.js +169 -0
  32. package/ai/.claude-plugin/plugin.json +9 -0
  33. package/ai/agents/testdriver.md +638 -0
  34. package/ai/skills/testdriver-ai/SKILL.md +204 -0
  35. package/ai/skills/testdriver-assert/SKILL.md +315 -0
  36. package/ai/skills/testdriver-aws-setup/SKILL.md +448 -0
  37. package/ai/skills/testdriver-cache/SKILL.md +221 -0
  38. package/ai/skills/testdriver-caching/SKILL.md +124 -0
  39. package/ai/skills/testdriver-captcha/SKILL.md +158 -0
  40. package/ai/skills/testdriver-ci-cd/SKILL.md +602 -0
  41. package/ai/skills/testdriver-click/SKILL.md +286 -0
  42. package/ai/skills/testdriver-client/SKILL.md +477 -0
  43. package/ai/skills/testdriver-cloud/SKILL.md +119 -0
  44. package/ai/skills/testdriver-customizing-devices/SKILL.md +319 -0
  45. package/ai/skills/testdriver-dashcam/SKILL.md +418 -0
  46. package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +401 -0
  47. package/ai/skills/testdriver-device-config/SKILL.md +317 -0
  48. package/ai/skills/testdriver-double-click/SKILL.md +102 -0
  49. package/ai/skills/testdriver-elements/SKILL.md +605 -0
  50. package/ai/skills/testdriver-enterprise/SKILL.md +114 -0
  51. package/ai/skills/testdriver-errors/SKILL.md +246 -0
  52. package/ai/skills/testdriver-events/SKILL.md +356 -0
  53. package/ai/skills/testdriver-examples/SKILL.md +7 -0
  54. package/ai/skills/testdriver-exec/SKILL.md +317 -0
  55. package/ai/skills/testdriver-find/SKILL.md +829 -0
  56. package/ai/skills/testdriver-focus-application/SKILL.md +293 -0
  57. package/ai/skills/testdriver-generating-tests/SKILL.md +36 -0
  58. package/ai/skills/testdriver-hover/SKILL.md +278 -0
  59. package/ai/skills/testdriver-locating-elements/SKILL.md +71 -0
  60. package/ai/skills/testdriver-making-assertions/SKILL.md +32 -0
  61. package/ai/skills/testdriver-mcp/SKILL.md +7 -0
  62. package/ai/skills/testdriver-mcp-workflow/SKILL.md +410 -0
  63. package/ai/skills/testdriver-mouse-down/SKILL.md +161 -0
  64. package/ai/skills/testdriver-mouse-up/SKILL.md +164 -0
  65. package/ai/skills/testdriver-parse/SKILL.md +236 -0
  66. package/ai/skills/testdriver-performing-actions/SKILL.md +54 -0
  67. package/ai/skills/testdriver-press-keys/SKILL.md +348 -0
  68. package/ai/skills/testdriver-provision/SKILL.md +331 -0
  69. package/ai/skills/testdriver-quickstart/SKILL.md +144 -0
  70. package/ai/skills/testdriver-redraw/SKILL.md +214 -0
  71. package/ai/skills/testdriver-reusable-code/SKILL.md +249 -0
  72. package/ai/skills/testdriver-right-click/SKILL.md +123 -0
  73. package/ai/skills/testdriver-running-tests/SKILL.md +185 -0
  74. package/ai/skills/testdriver-screenshot/SKILL.md +248 -0
  75. package/ai/skills/testdriver-screenshots/SKILL.md +184 -0
  76. package/ai/skills/testdriver-scroll/SKILL.md +335 -0
  77. package/ai/skills/testdriver-secrets/SKILL.md +115 -0
  78. package/ai/skills/testdriver-self-hosted/SKILL.md +65 -0
  79. package/ai/skills/testdriver-test-writer/SKILL.md +448 -0
  80. package/ai/skills/testdriver-testdriver/SKILL.md +628 -0
  81. package/ai/skills/testdriver-testdriver-mechanic/SKILL.md +165 -0
  82. package/ai/skills/testdriver-type/SKILL.md +357 -0
  83. package/ai/skills/testdriver-variables/SKILL.md +111 -0
  84. package/ai/skills/testdriver-wait/SKILL.md +50 -0
  85. package/ai/skills/testdriver-waiting-for-elements/SKILL.md +90 -0
  86. package/ai/skills/testdriver-what-is-testdriver/SKILL.md +54 -0
  87. package/bin/testdriverai.js +22 -0
  88. package/debugger/bg.png +0 -0
  89. package/debugger/icon.png +0 -0
  90. package/debugger/index.html +469 -0
  91. package/debugger/td.png +0 -0
  92. package/debugger/tray-buffered.png +0 -0
  93. package/debugger/tray.png +0 -0
  94. package/docs/GITHUB_COMMENTS.md +330 -0
  95. package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
  96. package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
  97. package/docs/TEST-GITHUB-COMMENTS.md +129 -0
  98. package/docs/_data/examples-manifest.json +177 -0
  99. package/docs/_data/examples-manifest.schema.json +41 -0
  100. package/docs/_scripts/extract-example-urls.js +165 -0
  101. package/docs/_scripts/generate-examples.js +560 -0
  102. package/docs/_scripts/generate-skills.js +154 -0
  103. package/docs/_scripts/link-replacer.js +164 -0
  104. package/docs/_scripts/upload-docs-to-openai.js +284 -0
  105. package/docs/changelog.mdx +161 -0
  106. package/docs/claude-mcp-plugin.mdx +160 -0
  107. package/docs/docs.json +442 -0
  108. package/docs/github-integration-setup.md +266 -0
  109. package/docs/guide/best-practices-polling.mdx +174 -0
  110. package/docs/images/content/account/newprojectsettings.png +0 -0
  111. package/docs/images/content/account/projectpage.png +0 -0
  112. package/docs/images/content/account/projectreplays.png +0 -0
  113. package/docs/images/content/account/team-manage.png +0 -0
  114. package/docs/images/content/account/teampage.png +0 -0
  115. package/docs/images/content/extension/cursor.svg +1 -0
  116. package/docs/images/content/extension/vscode.svg +57 -0
  117. package/docs/images/content/extension/windsurf.svg +3 -0
  118. package/docs/images/content/parse/output.png +0 -0
  119. package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
  120. package/docs/images/content/side-by-side.png +0 -0
  121. package/docs/images/content/vscode/ide-full.png +0 -0
  122. package/docs/images/content/vscode/running.png +0 -0
  123. package/docs/images/content/vscode/v7-chat.png +0 -0
  124. package/docs/images/content/vscode/v7-choose-agent.png +0 -0
  125. package/docs/images/content/vscode/v7-full.png +0 -0
  126. package/docs/images/content/vscode/v7-onboarding.png +0 -0
  127. package/docs/images/content/vscode/vscode-2-assert.png +0 -0
  128. package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
  129. package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
  130. package/docs/images/content/vscode/vscode-file-creation.png +0 -0
  131. package/docs/images/content/vscode/vscode-install.png +0 -0
  132. package/docs/images/content/vscode/vscode-overview.png +0 -0
  133. package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
  134. package/docs/images/content/vscode/vscode-stopchat.png +0 -0
  135. package/docs/images/content/vscode/vscode-stoptest.png +0 -0
  136. package/docs/images/content/vscode/vscode-tdservice.png +0 -0
  137. package/docs/images/content/vscode/vscode-test-output.png +0 -0
  138. package/docs/images/content/vscode/vscode-testhistory.png +0 -0
  139. package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
  140. package/docs/images/content/vscode/vscode-testpane.png +0 -0
  141. package/docs/images/template/dark.png +0 -0
  142. package/docs/images/template/icon.png +0 -0
  143. package/docs/images/template/light.png +0 -0
  144. package/docs/snippets/calendar-link.mdx +4 -0
  145. package/docs/snippets/gitignore-warning.mdx +7 -0
  146. package/docs/snippets/lifecycle-warning.mdx +6 -0
  147. package/docs/snippets/test-prereqs.mdx +12 -0
  148. package/docs/snippets/tests/assert-replay.mdx +7 -0
  149. package/docs/snippets/tests/assert-yaml.mdx +8 -0
  150. package/docs/snippets/tests/exec-js-replay.mdx +7 -0
  151. package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
  152. package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
  153. package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
  154. package/docs/snippets/tests/hover-image-replay.mdx +7 -0
  155. package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
  156. package/docs/snippets/tests/hover-text-replay.mdx +7 -0
  157. package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
  158. package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
  159. package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
  160. package/docs/snippets/tests/match-image-replay.mdx +7 -0
  161. package/docs/snippets/tests/match-image-yaml.mdx +17 -0
  162. package/docs/snippets/tests/press-keys-replay.mdx +7 -0
  163. package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
  164. package/docs/snippets/tests/remember-replay.mdx +7 -0
  165. package/docs/snippets/tests/remember-yaml.mdx +28 -0
  166. package/docs/snippets/tests/scroll-replay.mdx +7 -0
  167. package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
  168. package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
  169. package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
  170. package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
  171. package/docs/snippets/tests/scroll-yaml.mdx +30 -0
  172. package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
  173. package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
  174. package/docs/snippets/tests/type-replay.mdx +7 -0
  175. package/docs/snippets/tests/type-yaml.mdx +28 -0
  176. package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
  177. package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
  178. package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
  179. package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
  180. package/docs/snippets/tests/wait-replay.mdx +7 -0
  181. package/docs/snippets/tests/wait-yaml.mdx +13 -0
  182. package/docs/styles.css +65 -0
  183. package/docs/v6/account/dashboard.mdx +16 -0
  184. package/docs/v6/account/enterprise.mdx +110 -0
  185. package/docs/v6/account/pricing.mdx +33 -0
  186. package/docs/v6/account/projects.mdx +33 -0
  187. package/docs/v6/account/team.mdx +35 -0
  188. package/docs/v6/action/ami.mdx +109 -0
  189. package/docs/v6/action/performance.mdx +105 -0
  190. package/docs/v6/action/secrets.mdx +93 -0
  191. package/docs/v6/apps/chrome-extensions.mdx +48 -0
  192. package/docs/v6/apps/desktop-apps.mdx +93 -0
  193. package/docs/v6/apps/mobile-apps.mdx +26 -0
  194. package/docs/v6/apps/static-websites.mdx +54 -0
  195. package/docs/v6/apps/tauri-apps.mdx +361 -0
  196. package/docs/v6/bugs/jira.mdx +232 -0
  197. package/docs/v6/cli/overview.mdx +66 -0
  198. package/docs/v6/commands/assert.mdx +45 -0
  199. package/docs/v6/commands/exec.mdx +276 -0
  200. package/docs/v6/commands/focus-application.mdx +44 -0
  201. package/docs/v6/commands/hover-image.mdx +69 -0
  202. package/docs/v6/commands/hover-text.mdx +47 -0
  203. package/docs/v6/commands/if.mdx +53 -0
  204. package/docs/v6/commands/match-image.mdx +67 -0
  205. package/docs/v6/commands/press-keys.mdx +87 -0
  206. package/docs/v6/commands/remember.mdx +49 -0
  207. package/docs/v6/commands/run.mdx +44 -0
  208. package/docs/v6/commands/scroll-until-image.mdx +66 -0
  209. package/docs/v6/commands/scroll-until-text.mdx +60 -0
  210. package/docs/v6/commands/scroll.mdx +69 -0
  211. package/docs/v6/commands/type.mdx +45 -0
  212. package/docs/v6/commands/wait-for-image.mdx +54 -0
  213. package/docs/v6/commands/wait-for-text.mdx +48 -0
  214. package/docs/v6/commands/wait.mdx +45 -0
  215. package/docs/v6/exporting/junit.mdx +218 -0
  216. package/docs/v6/exporting/playwright.mdx +197 -0
  217. package/docs/v6/features/auto-healing.mdx +144 -0
  218. package/docs/v6/features/generation.mdx +116 -0
  219. package/docs/v6/features/parallel-testing.mdx +151 -0
  220. package/docs/v6/features/reusable-snippets.mdx +131 -0
  221. package/docs/v6/features/selectorless.mdx +80 -0
  222. package/docs/v6/features/visual-assertions.mdx +139 -0
  223. package/docs/v6/getting-started/ci.mdx +146 -0
  224. package/docs/v6/getting-started/cli.mdx +91 -0
  225. package/docs/v6/getting-started/editing.mdx +100 -0
  226. package/docs/v6/getting-started/playwright.mdx +342 -0
  227. package/docs/v6/getting-started/running.mdx +48 -0
  228. package/docs/v6/getting-started/self-hosting.mdx +408 -0
  229. package/docs/v6/getting-started/vscode.mdx +88 -0
  230. package/docs/v6/guide/assertions.mdx +189 -0
  231. package/docs/v6/guide/authentication.mdx +136 -0
  232. package/docs/v6/guide/code.mdx +65 -0
  233. package/docs/v6/guide/dashcam.mdx +118 -0
  234. package/docs/v6/guide/environment-variables.mdx +26 -0
  235. package/docs/v6/guide/lifecycle.mdx +242 -0
  236. package/docs/v6/guide/locating.mdx +141 -0
  237. package/docs/v6/guide/protips.mdx +43 -0
  238. package/docs/v6/guide/variables.mdx +143 -0
  239. package/docs/v6/guide/waiting.mdx +130 -0
  240. package/docs/v6/importing/csv.mdx +196 -0
  241. package/docs/v6/importing/gherkin.mdx +143 -0
  242. package/docs/v6/importing/jira.mdx +164 -0
  243. package/docs/v6/importing/testrail.mdx +162 -0
  244. package/docs/v6/integrations/electron.mdx +146 -0
  245. package/docs/v6/integrations/netlify.mdx +100 -0
  246. package/docs/v6/integrations/vercel.mdx +125 -0
  247. package/docs/v6/interactive/explore.mdx +99 -0
  248. package/docs/v6/interactive/run.mdx +52 -0
  249. package/docs/v6/interactive/save.mdx +63 -0
  250. package/docs/v6/overview/comparison.mdx +101 -0
  251. package/docs/v6/overview/faq.mdx +162 -0
  252. package/docs/v6/overview/performance.mdx +52 -0
  253. package/docs/v6/overview/quickstart.mdx +137 -0
  254. package/docs/v6/overview/what-is-testdriver.mdx +85 -0
  255. package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
  256. package/docs/v6/scenarios/cookie-banner.mdx +32 -0
  257. package/docs/v6/scenarios/file-upload.mdx +33 -0
  258. package/docs/v6/scenarios/form-filling.mdx +32 -0
  259. package/docs/v6/scenarios/log-in.mdx +75 -0
  260. package/docs/v6/scenarios/pdf-generation.mdx +25 -0
  261. package/docs/v6/scenarios/spell-check.mdx +22 -0
  262. package/docs/v6/security/action.mdx +84 -0
  263. package/docs/v6/security/agent.mdx +73 -0
  264. package/docs/v6/security/platform.mdx +77 -0
  265. package/docs/v6/tutorials/advanced-test.mdx +81 -0
  266. package/docs/v6/tutorials/basic-test.mdx +45 -0
  267. package/docs/v7/_drafts/agents.mdx +843 -0
  268. package/docs/v7/_drafts/architecture.mdx +399 -0
  269. package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
  270. package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
  271. package/docs/v7/_drafts/best-practices.mdx +486 -0
  272. package/docs/v7/_drafts/caching-ai.mdx +215 -0
  273. package/docs/v7/_drafts/caching-selectors.mdx +424 -0
  274. package/docs/v7/_drafts/caching.mdx +366 -0
  275. package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
  276. package/docs/v7/_drafts/commands/assert.mdx +45 -0
  277. package/docs/v7/_drafts/commands/exec.mdx +276 -0
  278. package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
  279. package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
  280. package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
  281. package/docs/v7/_drafts/commands/if.mdx +53 -0
  282. package/docs/v7/_drafts/commands/match-image.mdx +67 -0
  283. package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
  284. package/docs/v7/_drafts/commands/remember.mdx +49 -0
  285. package/docs/v7/_drafts/commands/run.mdx +44 -0
  286. package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
  287. package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
  288. package/docs/v7/_drafts/commands/scroll.mdx +69 -0
  289. package/docs/v7/_drafts/commands/type.mdx +45 -0
  290. package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
  291. package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
  292. package/docs/v7/_drafts/commands/wait.mdx +45 -0
  293. package/docs/v7/_drafts/configuration.mdx +378 -0
  294. package/docs/v7/_drafts/contributing.mdx +174 -0
  295. package/docs/v7/_drafts/core.mdx +458 -0
  296. package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
  297. package/docs/v7/_drafts/debugging.mdx +349 -0
  298. package/docs/v7/_drafts/error-handling.mdx +501 -0
  299. package/docs/v7/_drafts/faq.mdx +393 -0
  300. package/docs/v7/_drafts/hooks.mdx +360 -0
  301. package/docs/v7/_drafts/init-command.mdx +95 -0
  302. package/docs/v7/_drafts/installation.mdx +420 -0
  303. package/docs/v7/_drafts/migration.mdx +562 -0
  304. package/docs/v7/_drafts/observable.mdx +604 -0
  305. package/docs/v7/_drafts/playwright.mdx +342 -0
  306. package/docs/v7/_drafts/plugin-migration.mdx +220 -0
  307. package/docs/v7/_drafts/powerful.mdx +419 -0
  308. package/docs/v7/_drafts/presets.mdx +210 -0
  309. package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
  310. package/docs/v7/_drafts/prompt-cache.mdx +200 -0
  311. package/docs/v7/_drafts/provision.mdx +390 -0
  312. package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
  313. package/docs/v7/_drafts/readme.mdx +135 -0
  314. package/docs/v7/_drafts/reports.mdx +414 -0
  315. package/docs/v7/_drafts/scalable.mdx +763 -0
  316. package/docs/v7/_drafts/screenshot.mdx +155 -0
  317. package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
  318. package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
  319. package/docs/v7/_drafts/sdk-migration.mdx +474 -0
  320. package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
  321. package/docs/v7/_drafts/self-hosting.mdx +369 -0
  322. package/docs/v7/_drafts/test-recording.mdx +382 -0
  323. package/docs/v7/_drafts/troubleshooting.mdx +526 -0
  324. package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
  325. package/docs/v7/_drafts/vitest.mdx +535 -0
  326. package/docs/v7/_drafts/writing-tests.mdx +25 -0
  327. package/docs/v7/ai.mdx +205 -0
  328. package/docs/v7/assert.mdx +316 -0
  329. package/docs/v7/aws-setup.mdx +449 -0
  330. package/docs/v7/cache.mdx +223 -0
  331. package/docs/v7/caching.mdx +128 -0
  332. package/docs/v7/captcha.mdx +159 -0
  333. package/docs/v7/ci-cd.mdx +603 -0
  334. package/docs/v7/click.mdx +287 -0
  335. package/docs/v7/client.mdx +478 -0
  336. package/docs/v7/copilot/auto-healing.mdx +265 -0
  337. package/docs/v7/copilot/creating-tests.mdx +156 -0
  338. package/docs/v7/copilot/github.mdx +143 -0
  339. package/docs/v7/copilot/running-tests.mdx +149 -0
  340. package/docs/v7/copilot/setup.mdx +143 -0
  341. package/docs/v7/customizing-devices.mdx +319 -0
  342. package/docs/v7/dashcam.mdx +419 -0
  343. package/docs/v7/debugging-with-screenshots.mdx +402 -0
  344. package/docs/v7/device-config.mdx +317 -0
  345. package/docs/v7/double-click.mdx +102 -0
  346. package/docs/v7/elements.mdx +606 -0
  347. package/docs/v7/enterprise.mdx +9 -0
  348. package/docs/v7/errors.mdx +248 -0
  349. package/docs/v7/events.mdx +358 -0
  350. package/docs/v7/examples/ai.mdx +72 -0
  351. package/docs/v7/examples/assert.mdx +72 -0
  352. package/docs/v7/examples/captcha-api.mdx +92 -0
  353. package/docs/v7/examples/chrome-extension.mdx +132 -0
  354. package/docs/v7/examples/drag-and-drop.mdx +100 -0
  355. package/docs/v7/examples/element-not-found.mdx +67 -0
  356. package/docs/v7/examples/exec-output.mdx +85 -0
  357. package/docs/v7/examples/exec-pwsh.mdx +83 -0
  358. package/docs/v7/examples/focus-window.mdx +62 -0
  359. package/docs/v7/examples/hover-image.mdx +94 -0
  360. package/docs/v7/examples/hover-text.mdx +69 -0
  361. package/docs/v7/examples/installer.mdx +91 -0
  362. package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
  363. package/docs/v7/examples/match-image.mdx +96 -0
  364. package/docs/v7/examples/press-keys.mdx +92 -0
  365. package/docs/v7/examples/scroll-keyboard.mdx +79 -0
  366. package/docs/v7/examples/scroll-until-image.mdx +81 -0
  367. package/docs/v7/examples/scroll-until-text.mdx +109 -0
  368. package/docs/v7/examples/scroll.mdx +81 -0
  369. package/docs/v7/examples/type.mdx +92 -0
  370. package/docs/v7/examples/windows-installer.mdx +89 -0
  371. package/docs/v7/exec.mdx +318 -0
  372. package/docs/v7/find.mdx +830 -0
  373. package/docs/v7/focus-application.mdx +294 -0
  374. package/docs/v7/generating-tests.mdx +36 -0
  375. package/docs/v7/hosted.mdx +158 -0
  376. package/docs/v7/hover.mdx +279 -0
  377. package/docs/v7/locating-elements.mdx +71 -0
  378. package/docs/v7/making-assertions.mdx +32 -0
  379. package/docs/v7/mcp.mdx +9 -0
  380. package/docs/v7/mouse-down.mdx +161 -0
  381. package/docs/v7/mouse-up.mdx +164 -0
  382. package/docs/v7/parse.mdx +237 -0
  383. package/docs/v7/performing-actions.mdx +54 -0
  384. package/docs/v7/press-keys.mdx +349 -0
  385. package/docs/v7/provision.mdx +333 -0
  386. package/docs/v7/quickstart.mdx +173 -0
  387. package/docs/v7/redraw.mdx +216 -0
  388. package/docs/v7/reusable-code.mdx +249 -0
  389. package/docs/v7/right-click.mdx +123 -0
  390. package/docs/v7/running-tests.mdx +185 -0
  391. package/docs/v7/screenshot.mdx +249 -0
  392. package/docs/v7/screenshots.mdx +186 -0
  393. package/docs/v7/scroll.mdx +336 -0
  394. package/docs/v7/secrets.mdx +115 -0
  395. package/docs/v7/self-hosted.mdx +149 -0
  396. package/docs/v7/type.mdx +358 -0
  397. package/docs/v7/variables.mdx +111 -0
  398. package/docs/v7/wait.mdx +52 -0
  399. package/docs/v7/waiting-for-elements.mdx +90 -0
  400. package/docs/v7/what-is-testdriver.mdx +54 -0
  401. package/eslint.config.js +67 -0
  402. package/examples/ai.test.mjs +31 -0
  403. package/examples/assert.test.mjs +47 -0
  404. package/examples/chrome-extension.test.mjs +97 -0
  405. package/examples/config.mjs +5 -0
  406. package/examples/element-not-found.test.mjs +27 -0
  407. package/examples/exec-output.test.mjs +60 -0
  408. package/examples/exec-pwsh.test.mjs +58 -0
  409. package/examples/findall-coffee-icons.test.mjs +42 -0
  410. package/examples/focus-window.test.mjs +37 -0
  411. package/examples/formatted-logging.test.mjs +27 -0
  412. package/examples/hover-image.test.mjs +53 -0
  413. package/examples/hover-text-with-description.test.mjs +57 -0
  414. package/examples/hover-text.test.mjs +28 -0
  415. package/examples/installer.test.mjs +50 -0
  416. package/examples/launch-vscode-linux.test.mjs +55 -0
  417. package/examples/match-image.test.mjs +55 -0
  418. package/examples/parse.test.mjs +19 -0
  419. package/examples/press-keys.test.mjs +44 -0
  420. package/examples/prompt.test.mjs +34 -0
  421. package/examples/scroll-keyboard.test.mjs +38 -0
  422. package/examples/scroll-until-image.test.mjs +40 -0
  423. package/examples/scroll.test.mjs +42 -0
  424. package/examples/type.test.mjs +46 -0
  425. package/examples/windows-installer.test.mjs +54 -0
  426. package/index.js +2 -0
  427. package/interfaces/cli/commands/init.js +438 -0
  428. package/interfaces/cli/commands/setup.js +382 -0
  429. package/interfaces/cli/lib/base.js +285 -0
  430. package/interfaces/cli.js +20 -0
  431. package/interfaces/junit-reporter.js +290 -0
  432. package/interfaces/logger.js +388 -0
  433. package/interfaces/readline.js +234 -0
  434. package/interfaces/shared-test-state.mjs +64 -0
  435. package/interfaces/vitest-plugin.d.ts +115 -0
  436. package/interfaces/vitest-plugin.mjs +1698 -0
  437. package/lib/captcha/solver.js +358 -0
  438. package/lib/core/Dashcam.js +533 -0
  439. package/lib/core/index.d.ts +172 -0
  440. package/lib/core/index.js +12 -0
  441. package/lib/environments.json +18 -0
  442. package/lib/github-comment-formatter.js +263 -0
  443. package/lib/github-comment.mjs +452 -0
  444. package/lib/init-project.js +575 -0
  445. package/lib/presets/index.mjs +331 -0
  446. package/lib/resolve-channel.js +46 -0
  447. package/lib/sentry.js +417 -0
  448. package/lib/vitest/hooks.d.ts +57 -0
  449. package/lib/vitest/hooks.mjs +674 -0
  450. package/lib/vitest/setup-aws.mjs +247 -0
  451. package/lib/vitest/setup-self-hosted.mjs +151 -0
  452. package/lib/vitest/setup.mjs +46 -0
  453. package/manual/captcha-api.test.mjs +51 -0
  454. package/manual/drag-and-drop.test.mjs +59 -0
  455. package/manual/flake-diffthreshold-001.test.mjs +9 -0
  456. package/manual/flake-diffthreshold-01.test.mjs +9 -0
  457. package/manual/flake-diffthreshold-05.test.mjs +9 -0
  458. package/manual/flake-noredraw-cache.test.mjs +9 -0
  459. package/manual/flake-noredraw-nocache.test.mjs +9 -0
  460. package/manual/flake-redraw-cache.test.mjs +9 -0
  461. package/manual/flake-redraw-nocache.test.mjs +9 -0
  462. package/manual/flake-rocket-match.test.mjs +30 -0
  463. package/manual/flake-shared.mjs +51 -0
  464. package/manual/no-provision.test.mjs +31 -0
  465. package/manual/packer-hover-image.test.mjs +176 -0
  466. package/manual/scroll-until-text.test.mjs +68 -0
  467. package/manual/test-init-command.js +223 -0
  468. package/mcp-server/README.md +322 -0
  469. package/mcp-server/dist/codegen.d.ts +9 -0
  470. package/mcp-server/dist/codegen.js +165 -0
  471. package/mcp-server/dist/mcp-app.html +114 -0
  472. package/mcp-server/dist/package.json +1 -0
  473. package/mcp-server/dist/provision-types.d.ts +290 -0
  474. package/mcp-server/dist/provision-types.js +174 -0
  475. package/mcp-server/dist/server.d.ts +6 -0
  476. package/mcp-server/dist/server.mjs +1925 -0
  477. package/mcp-server/dist/session.d.ts +85 -0
  478. package/mcp-server/dist/session.js +152 -0
  479. package/mcp-server/mcp-app.html +28 -0
  480. package/mcp-server/mcp-config.example.json +19 -0
  481. package/mcp-server/package-lock.json +4027 -0
  482. package/mcp-server/package.json +31 -0
  483. package/mcp-server/src/codegen.ts +189 -0
  484. package/mcp-server/src/mcp-app.css +360 -0
  485. package/mcp-server/src/mcp-app.ts +547 -0
  486. package/mcp-server/src/provision-types.ts +209 -0
  487. package/mcp-server/src/server.ts +2391 -0
  488. package/mcp-server/src/session.ts +194 -0
  489. package/mcp-server/tsconfig.json +16 -0
  490. package/mcp-server/vite.config.ts +23 -0
  491. package/package.json +158 -0
  492. package/schema.json +1046 -0
  493. package/scripts/generate-skills.js +94 -0
  494. package/sdk-log-formatter.js +1157 -0
  495. package/sdk.d.ts +1486 -0
  496. package/sdk.js +4336 -0
  497. package/setup/aws/cloudformation.yaml +463 -0
  498. package/setup/aws/disable-defender.sh +42 -0
  499. package/setup/aws/install-dev-runner.sh +79 -0
  500. package/setup/aws/spawn-runner.sh +289 -0
  501. package/test/captcha-solver.test.mjs +152 -0
  502. package/test/chrome-remote-debugging.test.mjs +66 -0
  503. package/test/duckduckgo/experiment.test.mjs +28 -0
  504. package/test/duckduckgo/setup.test.mjs +29 -0
  505. package/test/manual/debug-locate-response.js +82 -0
  506. package/test/manual/reconnect-provision.test.mjs +49 -0
  507. package/test/manual/test-console-logs.test.mjs +42 -0
  508. package/test/manual/test-find-api.js +73 -0
  509. package/test/manual/test-init.sh +54 -0
  510. package/test/manual/test-prompt-cache.js +97 -0
  511. package/test/manual/test-provision-auth.mjs +22 -0
  512. package/test/manual/test-sandbox-render.js +29 -0
  513. package/test/manual/test-sdk-methods.js +15 -0
  514. package/test/manual/test-sdk-refactor.js +53 -0
  515. package/test/manual/test-stack-trace.mjs +57 -0
  516. package/test/manual/verify-element-api.js +89 -0
  517. package/test/manual/verify-types.js +0 -0
  518. package/test/manual-unawaited-promise.test.mjs +31 -0
  519. package/vitest.config.mjs +58 -0
  520. package/vitest.runner.config.mjs +33 -0
  521. package/vscode-extension/.vscodeignore +12 -0
  522. package/vscode-extension/README.md +94 -0
  523. package/vscode-extension/media/icon.png +0 -0
  524. package/vscode-extension/package-lock.json +4126 -0
  525. package/vscode-extension/package.json +86 -0
  526. package/vscode-extension/src/extension.ts +829 -0
  527. package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
  528. package/vscode-extension/tsconfig.json +16 -0
@@ -0,0 +1,60 @@
1
+ /**
2
+ * This file contains application config factory.
3
+ * It is responsible for creating config instances from environment variables,
4
+ * supplying defaults, and formatting values
5
+ */
6
+
7
+ // Parse out true and false string values
8
+ function parseValue(value) {
9
+ if (typeof value === "string") {
10
+ const normalizedValue = value.toLowerCase().trim();
11
+ if (["true", "false"].includes(normalizedValue)) {
12
+ return JSON.parse(normalizedValue);
13
+ }
14
+ }
15
+
16
+ return value;
17
+ }
18
+
19
+ const channelConfig = require("../../lib/resolve-channel.js");
20
+
21
+ // Factory function that creates a config instance
22
+ const createConfig = (environment = {}) => {
23
+ // Start with defaults
24
+ const config = {
25
+ TD_ANALYTICS: true,
26
+ TD_API_ROOT: channelConfig.channels[channelConfig.active],
27
+ TD_API_KEY: null,
28
+ TD_PROFILE: false,
29
+ TD_RESOLUTION: [1366, 768],
30
+ };
31
+
32
+ // Store the full environment for interpolation purposes
33
+ config._environment = environment;
34
+
35
+ // Find all env vars starting with TD_
36
+ for (let key in environment) {
37
+ if (key == "TD_RESOLUTION") {
38
+ config[key] = environment[key].split("x").map((x) => parseInt(x.trim()));
39
+ continue;
40
+ }
41
+
42
+ if (key.startsWith("TD_")) {
43
+ config[key] = parseValue(environment[key]);
44
+ }
45
+ }
46
+
47
+ // Add support for CI environment variable
48
+ if (environment.CI) {
49
+ config.CI = parseValue(environment.CI);
50
+ }
51
+
52
+ return config;
53
+ };
54
+
55
+ // Create a default config instance for backward compatibility
56
+ const defaultConfig = createConfig(process.env);
57
+
58
+ // Export both the factory function and the default instance
59
+ module.exports = defaultConfig;
60
+ module.exports.createConfig = createConfig;
@@ -0,0 +1,91 @@
1
+ // parses markdown content to find code blocks, and then extracts yaml from those code blocks
2
+ const yaml = require("js-yaml");
3
+ const pkg = require("../../package.json");
4
+ const session = require("./session");
5
+ const theme = require("./theme");
6
+ // do the actual parsing
7
+ // this library is very strict
8
+ // note that errors are sent to the AI will it may self-heal
9
+ const manualToYml = async function (inputArgs) {
10
+ // input is like `command=click x=100 y=200 z='this is a string'`
11
+ // convert this to json
12
+
13
+ const pattern = /(\w+)=('[^']*'|[^\s]+)/g;
14
+
15
+ let match;
16
+ let json = {};
17
+
18
+ while ((match = pattern.exec(inputArgs)) !== null) {
19
+ const key = match[1];
20
+ const value = match[2].replace(/'/g, ""); // Remove single quotes if present
21
+ json[key] = value;
22
+ }
23
+
24
+ json = {
25
+ commands: [json],
26
+ };
27
+
28
+ // use yml dump to convert json to yml
29
+ let yml = await yaml.dump(json);
30
+
31
+ return yml;
32
+ };
33
+
34
+ const jsonToManual = function (json, colors = true) {
35
+ // Convert the JSON object to key-value pairs
36
+ const params = Object.keys(json)
37
+ .map((key) => {
38
+ let value = json[key];
39
+
40
+ // If the value contains spaces, wrap it in single quotes
41
+ if (typeof value === "string") {
42
+ value = `'${value}'`;
43
+ }
44
+
45
+ if (colors) {
46
+ return `${theme.cyan(key)}=${theme.green(value)}`;
47
+ } else {
48
+ return `${key}=${value}`;
49
+ }
50
+ })
51
+ .join(" ");
52
+
53
+ return params;
54
+ };
55
+
56
+ const dumpToYML = async function (inputArray, sessionInstance = null) {
57
+ // use yml dump to convert json to yml
58
+ let yml = await yaml.dump({
59
+ version: pkg.version,
60
+ session: sessionInstance ? sessionInstance.get() : session.get(),
61
+ steps: inputArray,
62
+ });
63
+
64
+ return yml;
65
+ };
66
+
67
+ const hydrateFromYML = async function (yml, sessionInstance = null) {
68
+ // use yml load to convert yml to json
69
+ let json = await yaml.load(yml);
70
+
71
+ if (!json) {
72
+ json = {};
73
+ }
74
+
75
+ const sessionToUse = sessionInstance || session;
76
+
77
+ if (!json?.session) {
78
+ json.session = sessionToUse.get();
79
+ }
80
+
81
+ sessionToUse.set(json.session);
82
+
83
+ return json;
84
+ };
85
+
86
+ module.exports = {
87
+ manualToYml,
88
+ dumpToYML,
89
+ hydrateFromYML,
90
+ jsonToManual,
91
+ };
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Shared HTTP client for the TestDriver SDK.
3
+ *
4
+ * All SDK HTTP traffic should go through these helpers so that
5
+ * User-Agent, timeouts, Sentry tracing headers, and response
6
+ * parsing are handled in one place.
7
+ *
8
+ * Uses axios under the hood — the same library the rest of the SDK
9
+ * already depends on.
10
+ */
11
+
12
+ const axios = require("axios");
13
+ const crypto = require("crypto");
14
+ const { version } = require("../../package.json");
15
+
16
+ const USER_AGENT = `TestDriverSDK/${version} (Node.js ${process.version})`;
17
+
18
+ /**
19
+ * Generate Sentry distributed-tracing headers from a session ID.
20
+ * Both sandbox.js and sdk.js duplicated this — it now lives here.
21
+ *
22
+ * @param {string} sessionId
23
+ * @returns {object} Headers object (empty if no sessionId)
24
+ */
25
+ function getSentryTraceHeaders(sessionId) {
26
+ if (!sessionId) return {};
27
+ const traceId = crypto.createHash("md5").update(sessionId).digest("hex");
28
+ const spanId = crypto.randomBytes(8).toString("hex");
29
+ return {
30
+ "sentry-trace": traceId + "-" + spanId + "-1",
31
+ baggage:
32
+ "sentry-trace_id=" +
33
+ traceId +
34
+ ",sentry-sample_rate=1.0,sentry-sampled=true",
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Build common request headers.
40
+ * @param {object} [extra] - Additional headers to merge
41
+ * @returns {object}
42
+ */
43
+ function baseHeaders(extra) {
44
+ return {
45
+ "User-Agent": USER_AGENT,
46
+ ...extra,
47
+ };
48
+ }
49
+
50
+ /**
51
+ * POST JSON to `url` and return the parsed response body.
52
+ *
53
+ * @param {string} url - Absolute URL
54
+ * @param {object} [data] - JSON body
55
+ * @param {object} [opts] - Extra axios config (headers, timeout, …)
56
+ * @returns {Promise<object>} Parsed response data
57
+ */
58
+ async function httpPost(url, data, opts = {}) {
59
+ const { headers: extraHeaders, ...rest } = opts;
60
+ const res = await axios({
61
+ method: "post",
62
+ url,
63
+ headers: baseHeaders({
64
+ "Content-Type": "application/json",
65
+ ...extraHeaders,
66
+ }),
67
+ data,
68
+ timeout: opts.timeout || 30000,
69
+ ...rest,
70
+ });
71
+ return res.data;
72
+ }
73
+
74
+ /**
75
+ * GET `url` and return the parsed response body.
76
+ *
77
+ * @param {string} url - Absolute URL
78
+ * @param {object} [opts] - Extra axios config
79
+ * @returns {Promise<object>} Parsed response data
80
+ */
81
+ async function httpGet(url, opts = {}) {
82
+ const { headers: extraHeaders, ...rest } = opts;
83
+ const res = await axios({
84
+ method: "get",
85
+ url,
86
+ headers: baseHeaders(extraHeaders),
87
+ timeout: opts.timeout || 30000,
88
+ ...rest,
89
+ });
90
+ return res.data;
91
+ }
92
+
93
+ /**
94
+ * PUT data to `url` (e.g. S3 presigned upload).
95
+ *
96
+ * @param {string} url - Absolute URL
97
+ * @param {Buffer|string} data - Request body
98
+ * @param {object} [opts] - Extra axios config (headers, timeout, …)
99
+ * @returns {Promise<object>} Parsed response data (or empty object for 2xx with no body)
100
+ */
101
+ async function httpPut(url, data, opts = {}) {
102
+ const { headers: extraHeaders, ...rest } = opts;
103
+ const res = await axios({
104
+ method: "put",
105
+ url,
106
+ headers: baseHeaders(extraHeaders),
107
+ data,
108
+ timeout: opts.timeout || 30000,
109
+ maxBodyLength: Infinity,
110
+ maxContentLength: Infinity,
111
+ ...rest,
112
+ });
113
+ return res.data;
114
+ }
115
+
116
+ /**
117
+ * Download a URL as a Buffer (e.g. screenshot from S3).
118
+ *
119
+ * @param {string} url - Absolute URL
120
+ * @param {object} [opts] - Extra axios config
121
+ * @returns {Promise<Buffer>}
122
+ */
123
+ async function downloadBuffer(url, opts = {}) {
124
+ const { headers: extraHeaders, ...rest } = opts;
125
+ const res = await axios({
126
+ method: "get",
127
+ url,
128
+ headers: baseHeaders(extraHeaders),
129
+ responseType: "arraybuffer",
130
+ timeout: opts.timeout || 60000,
131
+ ...rest,
132
+ });
133
+ return Buffer.from(res.data);
134
+ }
135
+
136
+ module.exports = {
137
+ httpPost,
138
+ httpGet,
139
+ httpPut,
140
+ downloadBuffer,
141
+ getSentryTraceHeaders,
142
+ USER_AGENT,
143
+ baseHeaders,
144
+ };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Logger utility for TestDriver
3
+ *
4
+ * By default, outputs to stdout (console.log).
5
+ * When TD_STDIO=stderr is set, outputs to stderr (console.error).
6
+ * This is necessary for MCP servers which use stdout exclusively for JSON-RPC.
7
+ */
8
+
9
+ const useStderr = process.env.TD_STDIO === 'stderr';
10
+
11
+ /**
12
+ * Log a message - uses stdout by default, stderr if TD_STDIO=stderr
13
+ * @param {...any} args - Arguments to log
14
+ */
15
+ function log(...args) {
16
+ if (useStderr) {
17
+ console.error(...args);
18
+ } else {
19
+ console.log(...args);
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Log an error - always uses stderr
25
+ * @param {...any} args - Arguments to log
26
+ */
27
+ function error(...args) {
28
+ console.error(...args);
29
+ }
30
+
31
+ /**
32
+ * Log a warning - uses stdout by default, stderr if TD_STDIO=stderr
33
+ * @param {...any} args - Arguments to log
34
+ */
35
+ function warn(...args) {
36
+ if (useStderr) {
37
+ console.error(...args);
38
+ } else {
39
+ console.warn(...args);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Check if logger is configured to use stderr
45
+ * @returns {boolean}
46
+ */
47
+ function isStderrMode() {
48
+ return useStderr;
49
+ }
50
+
51
+ module.exports = {
52
+ log,
53
+ error,
54
+ warn,
55
+ isStderrMode,
56
+ };
@@ -0,0 +1,29 @@
1
+ // Factory function to create outputs instance
2
+ function createOutputs() {
3
+ let outputs = {};
4
+
5
+ return {
6
+ getAll: () => {
7
+ return outputs;
8
+ },
9
+ get: (key) => {
10
+ return outputs[key] || null;
11
+ },
12
+ set: (key, value) => {
13
+ if (key && value) {
14
+ outputs[key] = value;
15
+ }
16
+ },
17
+ };
18
+ }
19
+
20
+ // Export both factory function and legacy static instance for backward compatibility
21
+ const staticOutputs = createOutputs();
22
+
23
+ module.exports = {
24
+ createOutputs,
25
+ // Legacy static exports for backward compatibility
26
+ getAll: staticOutputs.getAll,
27
+ get: staticOutputs.get,
28
+ set: staticOutputs.set,
29
+ };
@@ -0,0 +1,209 @@
1
+ // parses markdown content to find code blocks, and then extracts yaml from those code blocks
2
+ const Parser = require("markdown-parser");
3
+ const yaml = require("js-yaml");
4
+ const Ajv = require("ajv/dist/2020");
5
+ const theme = require("./theme");
6
+ const { events } = require("../events.js");
7
+
8
+ let parser = new Parser();
9
+
10
+ function formatAjvError(error) {
11
+ return [
12
+ theme.red("Validation Failure"),
13
+ `${theme.yellow("Path:")} ${theme.white(error.instancePath)}`,
14
+ `${theme.yellow("Schema:")} ${theme.cyan(error.schemaPath)}`,
15
+ `${theme.yellow("Keyword:")} ${theme.magenta(error.keyword)}`,
16
+ error.params?.missingProperty
17
+ ? `${theme.yellow("Missing:")} ${theme.yellow(
18
+ error.params.missingProperty,
19
+ )}`
20
+ : "",
21
+ `${theme.yellow("Message:")} ${theme.white(error.message)}`,
22
+ `\n`,
23
+ ]
24
+ .filter(Boolean)
25
+ .join("\n");
26
+ }
27
+
28
+ // use markdown parser to find code blocks within AI response
29
+ const findCodeBlocks = async function (markdownContent) {
30
+ let md = markdownContent.match(/```yaml\n([\s\S]*?)```/);
31
+
32
+ if (md) {
33
+ return [{ code: md[1] }];
34
+ } else {
35
+ return [];
36
+ }
37
+ };
38
+
39
+ // use markdown parser to find code blocks within AI response
40
+ const findGenerativePrompts = async function (markdownContent) {
41
+ return new Promise((resolve, reject) => {
42
+ parser.parse(markdownContent, async (err, result) => {
43
+ if (err) {
44
+ return reject(err);
45
+ }
46
+
47
+ // parse the markdown content of each code block
48
+ let codes = result.codes.map((code) => {
49
+ return new Promise((resolve2, reject2) => {
50
+ try {
51
+ const yamlContent = getYAMLFromCodeBlock(code);
52
+ const parsedYaml = parseYAML(yamlContent);
53
+ resolve2(parsedYaml);
54
+ } catch (err) {
55
+ reject2(err);
56
+ }
57
+ });
58
+ });
59
+
60
+ // use Promise.all to wait for all the promises to resolve
61
+ let parsedCodes = await Promise.all(codes);
62
+
63
+ return resolve(parsedCodes);
64
+ });
65
+ });
66
+ };
67
+
68
+ // parse the yml from the included codeblock and clean it up
69
+ const getYAMLFromCodeBlock = function (codeblock) {
70
+ let lines = codeblock.code.split("\n");
71
+
72
+ // if first line is yaml or yml, remove it
73
+ if (lines[0].indexOf("yaml") > -1 || lines[0].indexOf("yml") > -1) {
74
+ lines.shift();
75
+ }
76
+
77
+ // count the whitespace in each line, and remove the line if it's all whitespace
78
+ lines = lines.filter((line) => {
79
+ return line.trim().length > 0 && line.trim()[0] !== ",";
80
+ // sometimes it produces yaml with breaks, or just a single comma
81
+ });
82
+
83
+ return lines.join("\n");
84
+ };
85
+
86
+ // do the actual parsing
87
+ // this library is very strict
88
+ // note that errors are sent to the AI will it may self-heal
89
+ const parseYAML = async function (inputYaml) {
90
+ let doc = await yaml.load(inputYaml);
91
+ return doc;
92
+ };
93
+
94
+ // Replace ${VAR} with the value from the vars object
95
+ // Will skip variables that are not in the vars object
96
+ // Will skip escaped variables like \${VAR}
97
+ function interpolate(yaml, vars) {
98
+ let newyaml = yaml;
99
+ Object.keys(vars).forEach((key) => {
100
+ newyaml = newyaml.replace(
101
+ new RegExp(`(?<!\\\\)\\$\\{${key}\\}`, "g"),
102
+ vars[key],
103
+ );
104
+ });
105
+ // Replace \$ with $
106
+ newyaml = newyaml.replace(/\\(\${[^}]+})/g, "$1");
107
+
108
+ return newyaml;
109
+ }
110
+
111
+ // Function to gather all variables in the YAMl that have not been replaced
112
+ function collectUnreplacedVariables(yaml) {
113
+ let unreplaced = [];
114
+
115
+ // Use a regex to find all ${VAR} patterns
116
+ const regex = /\$\{([^}]+)\}/g;
117
+ let match;
118
+ while ((match = regex.exec(yaml)) !== null) {
119
+ const variable = match[1];
120
+ // Check if the variable is already in the unreplaced array
121
+ if (!unreplaced.includes(variable)) {
122
+ unreplaced.push(variable);
123
+ }
124
+ }
125
+
126
+ return unreplaced;
127
+ }
128
+
129
+ // Factory function to create parser with emitter
130
+ function createParser(emitter) {
131
+ // validate yaml using schema.json in root
132
+ let schema = require("../../schema.json");
133
+ const validateYAML = async function (yaml) {
134
+ let ajv = new Ajv({
135
+ allowUnionTypes: true,
136
+ strict: false,
137
+ });
138
+ let validate = ajv.compile(schema);
139
+ let valid = validate(await parseYAML(yaml));
140
+
141
+ if (!valid) {
142
+ validate.errors.forEach((err) => {
143
+ const formattedError = formatAjvError(err);
144
+ emitter.emit(events.error.fatal, formattedError);
145
+ });
146
+ // throw new Error("Invalid YAML");
147
+ }
148
+
149
+ return yaml;
150
+ };
151
+
152
+ return {
153
+ findCodeBlocks,
154
+ findGenerativePrompts,
155
+ getYAMLFromCodeBlock,
156
+ interpolate,
157
+ collectUnreplacedVariables,
158
+ validateYAML,
159
+ getCommands: async function (codeBlock) {
160
+ const yml = getYAMLFromCodeBlock(codeBlock);
161
+ let yamlArray = await parseYAML(yml);
162
+
163
+ let steps = yamlArray?.steps;
164
+
165
+ if (steps) {
166
+ let commands = [];
167
+
168
+ // combine them all as if they were a single step
169
+ steps.forEach((s) => {
170
+ commands = commands.concat(s.commands);
171
+ });
172
+
173
+ // filter undefined values
174
+ commands = commands.filter((r) => {
175
+ return r;
176
+ });
177
+
178
+ if (!commands.length) {
179
+ throw new Error(
180
+ "No actions found in yaml. Individual commands must be under the `commands` key.",
181
+ );
182
+ }
183
+
184
+ return commands;
185
+ } else {
186
+ let commands = yamlArray?.commands;
187
+
188
+ if (!commands?.length) {
189
+ throw new Error(
190
+ "No actions found in yaml. Individual commands must be under the `commands` key.",
191
+ );
192
+ }
193
+
194
+ return commands;
195
+ }
196
+ },
197
+ };
198
+ }
199
+
200
+ // Export both the factory function and the static functions for backward compatibility
201
+ module.exports = {
202
+ createParser,
203
+ // Static exports for backward compatibility
204
+ findCodeBlocks,
205
+ findGenerativePrompts,
206
+ getYAMLFromCodeBlock,
207
+ interpolate,
208
+ collectUnreplacedVariables,
209
+ };