@testdriverai/agent 7.8.0-canary.10

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,290 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const { events } = require("../agent/events.js");
4
+ const builder = require("junit-report-builder");
5
+ const stripAnsi = require("strip-ansi");
6
+
7
+ /**
8
+ * JUnit XML Reporter for TestDriver
9
+ *
10
+ * Subscribes to TestDriver events and generates JUnit XML reports
11
+ * following the hierarchy:
12
+ * - Test Suite: folder path from "testdriver" root
13
+ * - Test Case: individual test file
14
+ * - Contains system-out from log:* events (ANSI codes stripped)
15
+ * - Contains system-err from error:* events (ANSI codes stripped)
16
+ * - Properties for each step (prompt) and their status
17
+ */
18
+ class JUnitReporter {
19
+ constructor(emitter, outputFilePath, mainTestFile) {
20
+ this.emitter = emitter;
21
+ this.outputFilePath = outputFilePath;
22
+ this.mainTestFile = mainTestFile;
23
+
24
+ // Current test state
25
+ this.currentTest = null;
26
+ this.currentTestCase = null;
27
+
28
+ // Single test suite for the run (based on main test file)
29
+ this.testSuite = null;
30
+
31
+ // Accumulate logs and errors for system-out/system-err
32
+ this.systemOut = [];
33
+ this.systemErr = [];
34
+
35
+ // Track step results for properties
36
+ this.stepResults = [];
37
+
38
+ // Track command results (including assertions)
39
+ this.commandResults = [];
40
+
41
+ // Track timing
42
+ this.testStartTime = null;
43
+
44
+ // Track final test result based on exit code
45
+ this.finalExitCode = null;
46
+
47
+ // Create test suite based on main test file
48
+ this.createTestSuite();
49
+
50
+ this.setupEventListeners();
51
+ }
52
+
53
+ createTestSuite() {
54
+ // Create test suite based on the main test file's folder
55
+ const suiteName = this.getTestSuiteName(this.mainTestFile);
56
+ this.testSuite = builder.testSuite().name(suiteName);
57
+ }
58
+
59
+ setupEventListeners() {
60
+ // Test lifecycle events
61
+ this.emitter.on(events.test.start, (data) => this.handleTestStart(data));
62
+
63
+ // Step lifecycle events
64
+ this.emitter.on(events.step.start, (data) => this.handleStepStart(data));
65
+ this.emitter.on(events.step.success, (data) =>
66
+ this.handleStepEnd(data, "passed"),
67
+ );
68
+ this.emitter.on(events.step.error, (data) =>
69
+ this.handleStepEnd(data, "failed"),
70
+ );
71
+
72
+ // Command lifecycle events (including assertions)
73
+ this.emitter.on(events.command.start, (data) =>
74
+ this.handleCommandStart(data),
75
+ );
76
+ this.emitter.on(events.command.success, (data) =>
77
+ this.handleCommandEnd(data, "passed"),
78
+ );
79
+ this.emitter.on(events.command.error, (data) =>
80
+ this.handleCommandEnd(data, "failed"),
81
+ );
82
+
83
+ // Log and error events for system-out/system-err
84
+ this.emitter.on("log:*", (message) => this.handleLogMessage(message));
85
+ this.emitter.on("error:*", (error) => this.handleErrorMessage(error));
86
+
87
+ // Handle exit to finalize report
88
+ this.emitter.on(events.exit, (exitCode) => this.finalizeReport(exitCode));
89
+ }
90
+
91
+ handleTestStart(data) {
92
+ const { filePath, timestamp } = data;
93
+ this.currentTest = { filePath, timestamp };
94
+ this.testStartTime = timestamp;
95
+
96
+ // Reset state for this test
97
+ this.systemOut = [];
98
+ this.systemErr = [];
99
+ this.stepResults = [];
100
+ this.commandResults = [];
101
+
102
+ // Create test case for the test file
103
+ const fileName = path.basename(filePath);
104
+ this.currentTestCase = this.testSuite
105
+ .testCase()
106
+ .className(this.getTestSuiteName(this.mainTestFile))
107
+ .name(fileName);
108
+ }
109
+
110
+ handleStepStart() {
111
+ // Step start is handled, the real work happens in handleStepEnd
112
+ }
113
+
114
+ handleStepEnd(data, status) {
115
+ // Only record steps if we have an active test
116
+ if (!this.currentTest) return;
117
+
118
+ // Extract step info from data
119
+ const prompt =
120
+ data.prompt || `Step ${data.stepIndex || this.stepResults.length}`;
121
+
122
+ // Record this step result
123
+ this.stepResults.push({
124
+ prompt: prompt,
125
+ status: status,
126
+ timestamp: data.timestamp,
127
+ });
128
+ }
129
+
130
+ handleCommandStart() {
131
+ // Commands are tracked but we wait for completion to record results
132
+ }
133
+
134
+ handleCommandEnd(data, status) {
135
+ // Only record commands if we have an active test
136
+ if (!this.currentTest) return;
137
+
138
+ // Extract command info from data
139
+ const command = data.command || "unknown";
140
+ const commandData = data.data || {};
141
+
142
+ // Record this command result
143
+ this.commandResults.push({
144
+ command: command,
145
+ status: status,
146
+ timestamp: data.timestamp,
147
+ expect: commandData.expect,
148
+ description: commandData.description || commandData.code || "",
149
+ });
150
+ }
151
+
152
+ handleLogMessage(message) {
153
+ // Only collect log messages if we have an active test running
154
+ if (!this.currentTest) return;
155
+
156
+ // Collect ALL log:* events for system-out, stripping ANSI codes
157
+ const cleanMessage = stripAnsi(message);
158
+ this.systemOut.push(`${cleanMessage}`);
159
+ }
160
+
161
+ handleErrorMessage(error) {
162
+ // Only collect error messages if we have an active test running
163
+ if (!this.currentTest) return;
164
+
165
+ // Collect ALL error:* events for system-err, stripping ANSI codes
166
+ const errorMessage =
167
+ typeof error === "string" ? error : JSON.stringify(error);
168
+ const cleanErrorMessage = stripAnsi(errorMessage);
169
+ this.systemErr.push(`${cleanErrorMessage}`);
170
+ }
171
+
172
+ getTestSuiteName(filePath) {
173
+ // Extract folder path from testdriver root to file
174
+ const relativePath = this.getRelativePathFromTestdriver(filePath);
175
+ const folderPath = path.dirname(relativePath);
176
+
177
+ // Create suite name from folder structure
178
+ return folderPath === "." ? "testdriver" : `testdriver/${folderPath}`;
179
+ }
180
+
181
+ getRelativePathFromTestdriver(filePath) {
182
+ // Find the "testdriver" directory in the path and return relative path from there
183
+ const testdriverIndex = filePath.toLowerCase().indexOf("/testdriver/");
184
+ if (testdriverIndex !== -1) {
185
+ return filePath.substring(testdriverIndex + "/testdriver/".length);
186
+ }
187
+
188
+ // Fallback: use just the filename
189
+ return path.basename(filePath);
190
+ }
191
+
192
+ finalizeReport(exitCode) {
193
+ // Store the exit code for determining test status
194
+ this.finalExitCode = exitCode;
195
+
196
+ // If we have a current test case that hasn't been finalized, finalize it now
197
+ if (this.currentTest && this.currentTestCase) {
198
+ const duration = this.testStartTime
199
+ ? (Date.now() - this.testStartTime) / 1000
200
+ : 0;
201
+
202
+ // Set test case duration
203
+ this.currentTestCase.time(duration);
204
+
205
+ // Add step results as properties
206
+ this.stepResults.forEach((step, index) => {
207
+ this.currentTestCase.property(
208
+ `step${index + 1}[${step.status}]`,
209
+ step.prompt,
210
+ );
211
+ });
212
+
213
+ // Add system-out and system-err
214
+ if (this.systemOut.length > 0) {
215
+ this.currentTestCase.standardOutput(this.systemOut.join("\n"));
216
+ }
217
+ if (this.systemErr.length > 0) {
218
+ this.currentTestCase.standardError(this.systemErr.join("\n"));
219
+ }
220
+
221
+ // Determine test result based on exit code (0 = success, non-zero = failure)
222
+ if (exitCode !== 0) {
223
+ // Test failed - collect failure information from steps and commands for detailed message
224
+ const failedSteps = this.stepResults.filter(
225
+ (step) => step.status === "failed",
226
+ );
227
+ const failedCommands = this.commandResults.filter(
228
+ (command) => command.status === "failed",
229
+ );
230
+
231
+ const failureMessages = [];
232
+ if (failedSteps.length > 0) {
233
+ failureMessages.push(
234
+ `Failed steps: ${failedSteps.map((s) => s.prompt).join(", ")}`,
235
+ );
236
+ }
237
+ if (failedCommands.length > 0) {
238
+ const failedAssertions = failedCommands.filter(
239
+ (c) => c.command === "assert",
240
+ );
241
+ const otherFailedCommands = failedCommands.filter(
242
+ (c) => c.command !== "assert",
243
+ );
244
+
245
+ if (failedAssertions.length > 0) {
246
+ failureMessages.push(
247
+ `Failed assertions: ${failedAssertions.map((c) => c.expect || "assertion").join(", ")}`,
248
+ );
249
+ }
250
+ if (otherFailedCommands.length > 0) {
251
+ failureMessages.push(
252
+ `Failed commands: ${otherFailedCommands.map((c) => c.command).join(", ")}`,
253
+ );
254
+ }
255
+ }
256
+
257
+ const failureMessage =
258
+ failureMessages.length > 0
259
+ ? failureMessages.join("; ")
260
+ : `Test failed with exit code ${exitCode}`;
261
+ this.currentTestCase.failure(failureMessage);
262
+ }
263
+ }
264
+
265
+ try {
266
+ // Generate the XML report
267
+ const xmlContent = builder.build();
268
+
269
+ // Ensure output directory exists
270
+ const outputDir = path.dirname(this.outputFilePath);
271
+ if (!fs.existsSync(outputDir)) {
272
+ fs.mkdirSync(outputDir, { recursive: true });
273
+ }
274
+
275
+ // Write to file
276
+ fs.writeFileSync(this.outputFilePath, xmlContent);
277
+ } catch (error) {
278
+ console.error("[JUnit Reporter] Failed to write JUnit report:", error);
279
+ }
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Factory function to create and initialize JUnit reporter
285
+ */
286
+ function createJUnitReporter(emitter, outputFilePath, mainTestFile) {
287
+ return new JUnitReporter(emitter, outputFilePath, mainTestFile);
288
+ }
289
+
290
+ module.exports = { JUnitReporter, createJUnitReporter };
@@ -0,0 +1,388 @@
1
+ // central logger for the bot
2
+ const winston = require("winston");
3
+ const chalk = require("chalk");
4
+ const theme = require("../agent/lib/theme");
5
+ const Transport = require("winston-transport");
6
+ const { events } = require("../agent/events");
7
+ class CustomTransport extends Transport {
8
+ constructor(opts) {
9
+ super(opts);
10
+ this.name = opts.name || "customTransport";
11
+ this.level = opts.level || "info";
12
+ this.logStore = opts.logStore || []; // You could connect to a DB or API here
13
+ this.sandbox = null;
14
+ }
15
+
16
+ log(info, callback) {
17
+ try {
18
+ const { message } = info;
19
+
20
+ if (typeof message === "object") {
21
+ console.log(chalk.cyan("protecting against base64 error"));
22
+ console.log(message);
23
+ callback();
24
+ return;
25
+ }
26
+
27
+ } catch (e) {
28
+ console.error("Error in CustomTransport log method:", e);
29
+ }
30
+
31
+ callback();
32
+ }
33
+ }
34
+
35
+ // responsible for rendering ai markdown output
36
+ const { marked } = require("marked");
37
+ const { markedTerminal } = require("marked-terminal");
38
+ const { censorSensitiveDataDeep } = require("../agent/lib/censorship");
39
+
40
+ const { printf } = winston.format;
41
+
42
+ const logFormat = printf(({ message }) => {
43
+ return `${message}`;
44
+ });
45
+
46
+ const logger = winston.createLogger({
47
+ format: winston.format.combine(
48
+ winston.format.splat(),
49
+ winston.format((info) => {
50
+ info.message = censorSensitiveDataDeep(info.message);
51
+ return info;
52
+ })(),
53
+ logFormat,
54
+ ),
55
+ transports: [
56
+ new winston.transports.Console(),
57
+ new CustomTransport({
58
+ level: "info",
59
+ logStore: [], // You could pass an external store or leave it empty
60
+ }),
61
+ ],
62
+ });
63
+
64
+ const plain = (codePart) => codePart;
65
+
66
+ // marked is a markdown parser
67
+ // markedTerminal allows us to render markdown in CLI
68
+ marked.use(
69
+ markedTerminal(
70
+ {
71
+ width: 58, // 58 is the width of the terminal output on a 16" macbook pro
72
+ reflowText: true,
73
+ tab: 2,
74
+ },
75
+ {
76
+ theme: {
77
+ /**
78
+ * keyword in a regular Algol-style language
79
+ */
80
+ keyword: theme.blue,
81
+
82
+ /**
83
+ * built-in or library object (constant, class, function)
84
+ */
85
+ built_in: theme.cyan,
86
+
87
+ /**
88
+ * user-defined type in a language with first-class syntactically significant types, like
89
+ * Haskell
90
+ */
91
+ type: theme.cyan,
92
+
93
+ /**
94
+ * special identifier for a built-in value ("true", "false", "null")
95
+ */
96
+ literal: theme.blue,
97
+
98
+ /**
99
+ * number, including units and modifiers, if any.
100
+ */
101
+ number: theme.green,
102
+
103
+ /**
104
+ * literal regular expression
105
+ */
106
+ regexp: theme.red,
107
+
108
+ /**
109
+ * literal string, character
110
+ */
111
+ string: theme.green,
112
+
113
+ /**
114
+ * parsed section inside a literal string
115
+ */
116
+ subst: plain,
117
+
118
+ /**
119
+ * symbolic constant, interned string, goto label
120
+ */
121
+ symbol: plain,
122
+
123
+ /**
124
+ * class or class-level declaration (interfaces, traits, modules, etc)
125
+ */
126
+ class: theme.blue,
127
+
128
+ /**
129
+ * function or method declaration
130
+ */
131
+ function: theme.yellow,
132
+
133
+ /**
134
+ * name of a class or a function at the place of declaration
135
+ */
136
+ title: plain,
137
+
138
+ /**
139
+ * block of function arguments (parameters) at the place of declaration
140
+ */
141
+ params: plain,
142
+
143
+ /**
144
+ * comment
145
+ */
146
+ comment: theme.green,
147
+
148
+ /**
149
+ * documentation markup within comments
150
+ */
151
+ doctag: theme.green,
152
+
153
+ /**
154
+ * flags, modifiers, annotations, processing instructions, preprocessor directive, etc
155
+ */
156
+ meta: theme.grey,
157
+
158
+ /**
159
+ * keyword or built-in within meta construct
160
+ */
161
+ "meta-keyword": plain,
162
+
163
+ /**
164
+ * string within meta construct
165
+ */
166
+ "meta-string": plain,
167
+
168
+ /**
169
+ * heading of a section in a config file, heading in text markup
170
+ */
171
+ section: plain,
172
+
173
+ /**
174
+ * XML/HTML tag
175
+ */
176
+ tag: theme.grey,
177
+
178
+ /**
179
+ * name of an XML tag, the first word in an s-expression
180
+ */
181
+ name: theme.blue,
182
+
183
+ /**
184
+ * s-expression name from the language standard library
185
+ */
186
+ "builtin-name": plain,
187
+
188
+ /**
189
+ * name of an attribute with no language defined semantics (keys in JSON, setting names in
190
+ * .ini), also sub-attribute within another highlighted object, like XML tag
191
+ */
192
+ attr: theme.cyan,
193
+
194
+ /**
195
+ * name of an attribute followed by a structured value part, like CSS properties
196
+ */
197
+ attribute: plain,
198
+
199
+ /**
200
+ * variable in a config or a template file, environment var expansion in a script
201
+ */
202
+ variable: plain,
203
+
204
+ /**
205
+ * list item bullet in text markup
206
+ */
207
+ bullet: plain,
208
+
209
+ /**
210
+ * code block in text markup
211
+ */
212
+ code: plain,
213
+
214
+ /**
215
+ * emphasis in text markup
216
+ */
217
+ emphasis: chalk.italic,
218
+
219
+ /**
220
+ * strong emphasis in text markup
221
+ */
222
+ strong: chalk.bold,
223
+
224
+ /**
225
+ * mathematical formula in text markup
226
+ */
227
+ formula: plain,
228
+
229
+ /**
230
+ * hyperlink in text markup
231
+ */
232
+ link: chalk.underline,
233
+
234
+ /**
235
+ * quotation in text markup
236
+ */
237
+ quote: plain,
238
+
239
+ /**
240
+ * tag selector in CSS
241
+ */
242
+ "selector-tag": plain,
243
+
244
+ /**
245
+ * #id selector in CSS
246
+ */
247
+ "selector-id": plain,
248
+
249
+ /**
250
+ * .class selector in CSS
251
+ */
252
+ "selector-class": plain,
253
+
254
+ /**
255
+ * [attr] selector in CSS
256
+ */
257
+ "selector-attr": plain,
258
+
259
+ /**
260
+ * :pseudo selector in CSS
261
+ */
262
+ "selector-pseudo": plain,
263
+
264
+ /**
265
+ * tag of a template language
266
+ */
267
+ "template-tag": plain,
268
+
269
+ /**
270
+ * variable in a template language
271
+ */
272
+ "template-variable": plain,
273
+
274
+ /**
275
+ * added or changed line in a diff
276
+ */
277
+ addition: theme.green,
278
+
279
+ /**
280
+ * deleted line in a diff
281
+ */
282
+ deletion: theme.red,
283
+
284
+ /**
285
+ * things not matched by any token
286
+ */
287
+ default: plain,
288
+ },
289
+ },
290
+ ),
291
+ );
292
+
293
+ const createMarkdownLogger = (emitter) => {
294
+ // Indent prefix for streaming AI thoughts - makes it visually distinct and scoped
295
+ const streamIndent = "";
296
+
297
+ const markedParsePartial = (markdown, start = 0, end = 0) => {
298
+ let result = markdown.trimEnd().split("\n").slice(start, end);
299
+ if (end <= 0) {
300
+ end = result.length + end;
301
+ }
302
+ result = result.join("\n");
303
+
304
+ // Use streamIndent for streaming output to make it visually scoped
305
+ return marked.parse(result).replace(/^/gm, streamIndent).trimEnd();
306
+ };
307
+
308
+ // Event-based markdown streaming with buffering
309
+ const activeStreams = new Map();
310
+
311
+ // Handle streaming markdown events with proper buffering
312
+ emitter.on(events.log.markdown.start, (streamId) => {
313
+ activeStreams.set(streamId, {
314
+ buffer: "",
315
+ lastOutput: "",
316
+ });
317
+ });
318
+
319
+ emitter.on(events.log.markdown.chunk, (streamId, chunk) => {
320
+ if (!activeStreams.has(streamId)) {
321
+ return;
322
+ }
323
+
324
+ const stream = activeStreams.get(streamId);
325
+
326
+ if (typeof chunk !== "string") {
327
+ return;
328
+ }
329
+
330
+ const previousConsoleOutput = markedParsePartial(stream.buffer, 0, -1);
331
+
332
+ stream.buffer += chunk;
333
+
334
+ const consoleOutput = markedParsePartial(stream.buffer, 0, -1);
335
+
336
+ let diff = consoleOutput.replace(previousConsoleOutput, "");
337
+ if (diff) {
338
+ diff = censorSensitiveDataDeep(diff);
339
+ process.stdout.write(diff);
340
+ }
341
+ });
342
+
343
+ emitter.on(events.log.markdown.end, (streamId) => {
344
+ if (!activeStreams.has(streamId)) {
345
+ return;
346
+ }
347
+
348
+ const stream = activeStreams.get(streamId);
349
+
350
+ const previousConsoleOutput = markedParsePartial(stream.buffer, 0, -1);
351
+ const consoleOutput = markedParsePartial(stream.buffer, 0, Infinity);
352
+ let diff = consoleOutput.replace(previousConsoleOutput, "");
353
+
354
+ if (diff) {
355
+ diff = censorSensitiveDataDeep(diff);
356
+ process.stdout.write(diff);
357
+ }
358
+ // Use console.log for the final newlines so it gets captured by vitest
359
+ console.log("");
360
+
361
+ // Clean up the stream
362
+ activeStreams.delete(streamId);
363
+ });
364
+
365
+ // Handle static markdown logging (complete markdown blocks)
366
+ emitter.on(events.log.markdown.static, (markdown) => {
367
+ if (typeof markdown !== "string") {
368
+ logger.error("Static markdown requires a string");
369
+ logger.error(markdown);
370
+ return;
371
+ }
372
+
373
+ let consoleOutput = marked.parse(markdown);
374
+
375
+ // strip newlines at end of consoleOutput
376
+ consoleOutput = consoleOutput.replace(/\n$/, "");
377
+ consoleOutput = consoleOutput.replace(/^/gm, spaceChar);
378
+
379
+ logger.info(consoleOutput);
380
+ });
381
+ };
382
+
383
+ const spaceChar = " ";
384
+
385
+ module.exports = {
386
+ logger,
387
+ createMarkdownLogger,
388
+ };