@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.
- package/.claude/settings.local.json +7 -0
- package/.env.example +4 -0
- package/.prettierignore +4 -0
- package/.prettierrc +1 -0
- package/CHANGELOG.md +953 -0
- package/README.md +81 -0
- package/agent/events.js +135 -0
- package/agent/index.js +2450 -0
- package/agent/interface.js +35 -0
- package/agent/lib/analytics.js +22 -0
- package/agent/lib/censorship.js +75 -0
- package/agent/lib/commander.js +246 -0
- package/agent/lib/commands.js +1684 -0
- package/agent/lib/config.js +60 -0
- package/agent/lib/generator.js +91 -0
- package/agent/lib/http.js +144 -0
- package/agent/lib/logger.js +56 -0
- package/agent/lib/outputs.js +29 -0
- package/agent/lib/parser.js +209 -0
- package/agent/lib/redraw.js +386 -0
- package/agent/lib/resources/cursor-2.png +0 -0
- package/agent/lib/sandbox.js +1104 -0
- package/agent/lib/sdk.js +633 -0
- package/agent/lib/session.js +25 -0
- package/agent/lib/source-mapper.js +342 -0
- package/agent/lib/subimage/index.js +77 -0
- package/agent/lib/subimage/opencv.js +69 -0
- package/agent/lib/system.js +204 -0
- package/agent/lib/theme.js +14 -0
- package/agent/lib/valid-version.js +21 -0
- package/agent/lib/validation.js +169 -0
- package/ai/.claude-plugin/plugin.json +9 -0
- package/ai/agents/testdriver.md +638 -0
- package/ai/skills/testdriver-ai/SKILL.md +204 -0
- package/ai/skills/testdriver-assert/SKILL.md +315 -0
- package/ai/skills/testdriver-aws-setup/SKILL.md +448 -0
- package/ai/skills/testdriver-cache/SKILL.md +221 -0
- package/ai/skills/testdriver-caching/SKILL.md +124 -0
- package/ai/skills/testdriver-captcha/SKILL.md +158 -0
- package/ai/skills/testdriver-ci-cd/SKILL.md +602 -0
- package/ai/skills/testdriver-click/SKILL.md +286 -0
- package/ai/skills/testdriver-client/SKILL.md +477 -0
- package/ai/skills/testdriver-cloud/SKILL.md +119 -0
- package/ai/skills/testdriver-customizing-devices/SKILL.md +319 -0
- package/ai/skills/testdriver-dashcam/SKILL.md +418 -0
- package/ai/skills/testdriver-debugging-with-screenshots/SKILL.md +401 -0
- package/ai/skills/testdriver-device-config/SKILL.md +317 -0
- package/ai/skills/testdriver-double-click/SKILL.md +102 -0
- package/ai/skills/testdriver-elements/SKILL.md +605 -0
- package/ai/skills/testdriver-enterprise/SKILL.md +114 -0
- package/ai/skills/testdriver-errors/SKILL.md +246 -0
- package/ai/skills/testdriver-events/SKILL.md +356 -0
- package/ai/skills/testdriver-examples/SKILL.md +7 -0
- package/ai/skills/testdriver-exec/SKILL.md +317 -0
- package/ai/skills/testdriver-find/SKILL.md +829 -0
- package/ai/skills/testdriver-focus-application/SKILL.md +293 -0
- package/ai/skills/testdriver-generating-tests/SKILL.md +36 -0
- package/ai/skills/testdriver-hover/SKILL.md +278 -0
- package/ai/skills/testdriver-locating-elements/SKILL.md +71 -0
- package/ai/skills/testdriver-making-assertions/SKILL.md +32 -0
- package/ai/skills/testdriver-mcp/SKILL.md +7 -0
- package/ai/skills/testdriver-mcp-workflow/SKILL.md +410 -0
- package/ai/skills/testdriver-mouse-down/SKILL.md +161 -0
- package/ai/skills/testdriver-mouse-up/SKILL.md +164 -0
- package/ai/skills/testdriver-parse/SKILL.md +236 -0
- package/ai/skills/testdriver-performing-actions/SKILL.md +54 -0
- package/ai/skills/testdriver-press-keys/SKILL.md +348 -0
- package/ai/skills/testdriver-provision/SKILL.md +331 -0
- package/ai/skills/testdriver-quickstart/SKILL.md +144 -0
- package/ai/skills/testdriver-redraw/SKILL.md +214 -0
- package/ai/skills/testdriver-reusable-code/SKILL.md +249 -0
- package/ai/skills/testdriver-right-click/SKILL.md +123 -0
- package/ai/skills/testdriver-running-tests/SKILL.md +185 -0
- package/ai/skills/testdriver-screenshot/SKILL.md +248 -0
- package/ai/skills/testdriver-screenshots/SKILL.md +184 -0
- package/ai/skills/testdriver-scroll/SKILL.md +335 -0
- package/ai/skills/testdriver-secrets/SKILL.md +115 -0
- package/ai/skills/testdriver-self-hosted/SKILL.md +65 -0
- package/ai/skills/testdriver-test-writer/SKILL.md +448 -0
- package/ai/skills/testdriver-testdriver/SKILL.md +628 -0
- package/ai/skills/testdriver-testdriver-mechanic/SKILL.md +165 -0
- package/ai/skills/testdriver-type/SKILL.md +357 -0
- package/ai/skills/testdriver-variables/SKILL.md +111 -0
- package/ai/skills/testdriver-wait/SKILL.md +50 -0
- package/ai/skills/testdriver-waiting-for-elements/SKILL.md +90 -0
- package/ai/skills/testdriver-what-is-testdriver/SKILL.md +54 -0
- package/bin/testdriverai.js +22 -0
- package/debugger/bg.png +0 -0
- package/debugger/icon.png +0 -0
- package/debugger/index.html +469 -0
- package/debugger/td.png +0 -0
- package/debugger/tray-buffered.png +0 -0
- package/debugger/tray.png +0 -0
- package/docs/GITHUB_COMMENTS.md +330 -0
- package/docs/GITHUB_COMMENTS_ANNOUNCEMENT.md +167 -0
- package/docs/QUICK-START-GITHUB-COMMENTS.md +84 -0
- package/docs/TEST-GITHUB-COMMENTS.md +129 -0
- package/docs/_data/examples-manifest.json +177 -0
- package/docs/_data/examples-manifest.schema.json +41 -0
- package/docs/_scripts/extract-example-urls.js +165 -0
- package/docs/_scripts/generate-examples.js +560 -0
- package/docs/_scripts/generate-skills.js +154 -0
- package/docs/_scripts/link-replacer.js +164 -0
- package/docs/_scripts/upload-docs-to-openai.js +284 -0
- package/docs/changelog.mdx +161 -0
- package/docs/claude-mcp-plugin.mdx +160 -0
- package/docs/docs.json +442 -0
- package/docs/github-integration-setup.md +266 -0
- package/docs/guide/best-practices-polling.mdx +174 -0
- package/docs/images/content/account/newprojectsettings.png +0 -0
- package/docs/images/content/account/projectpage.png +0 -0
- package/docs/images/content/account/projectreplays.png +0 -0
- package/docs/images/content/account/team-manage.png +0 -0
- package/docs/images/content/account/teampage.png +0 -0
- package/docs/images/content/extension/cursor.svg +1 -0
- package/docs/images/content/extension/vscode.svg +57 -0
- package/docs/images/content/extension/windsurf.svg +3 -0
- package/docs/images/content/parse/output.png +0 -0
- package/docs/images/content/self-hosted/launchtemplateid.png +0 -0
- package/docs/images/content/side-by-side.png +0 -0
- package/docs/images/content/vscode/ide-full.png +0 -0
- package/docs/images/content/vscode/running.png +0 -0
- package/docs/images/content/vscode/v7-chat.png +0 -0
- package/docs/images/content/vscode/v7-choose-agent.png +0 -0
- package/docs/images/content/vscode/v7-full.png +0 -0
- package/docs/images/content/vscode/v7-onboarding.png +0 -0
- package/docs/images/content/vscode/vscode-2-assert.png +0 -0
- package/docs/images/content/vscode/vscode-agent-preview.png +0 -0
- package/docs/images/content/vscode/vscode-copilot-ask.png +0 -0
- package/docs/images/content/vscode/vscode-file-creation.png +0 -0
- package/docs/images/content/vscode/vscode-install.png +0 -0
- package/docs/images/content/vscode/vscode-overview.png +0 -0
- package/docs/images/content/vscode/vscode-setup-walkthrough.png +0 -0
- package/docs/images/content/vscode/vscode-stopchat.png +0 -0
- package/docs/images/content/vscode/vscode-stoptest.png +0 -0
- package/docs/images/content/vscode/vscode-tdservice.png +0 -0
- package/docs/images/content/vscode/vscode-test-output.png +0 -0
- package/docs/images/content/vscode/vscode-testhistory.png +0 -0
- package/docs/images/content/vscode/vscode-testpane-runtests.png +0 -0
- package/docs/images/content/vscode/vscode-testpane.png +0 -0
- package/docs/images/template/dark.png +0 -0
- package/docs/images/template/icon.png +0 -0
- package/docs/images/template/light.png +0 -0
- package/docs/snippets/calendar-link.mdx +4 -0
- package/docs/snippets/gitignore-warning.mdx +7 -0
- package/docs/snippets/lifecycle-warning.mdx +6 -0
- package/docs/snippets/test-prereqs.mdx +12 -0
- package/docs/snippets/tests/assert-replay.mdx +7 -0
- package/docs/snippets/tests/assert-yaml.mdx +8 -0
- package/docs/snippets/tests/exec-js-replay.mdx +7 -0
- package/docs/snippets/tests/exec-js-yaml.mdx +32 -0
- package/docs/snippets/tests/exec-shell-replay.mdx +7 -0
- package/docs/snippets/tests/exec-shell-yaml.mdx +15 -0
- package/docs/snippets/tests/hover-image-replay.mdx +7 -0
- package/docs/snippets/tests/hover-image-yaml.mdx +17 -0
- package/docs/snippets/tests/hover-text-replay.mdx +7 -0
- package/docs/snippets/tests/hover-text-with-description-replay.mdx +7 -0
- package/docs/snippets/tests/hover-text-with-description-yaml.mdx +24 -0
- package/docs/snippets/tests/hover-text-yaml.mdx +14 -0
- package/docs/snippets/tests/match-image-replay.mdx +7 -0
- package/docs/snippets/tests/match-image-yaml.mdx +17 -0
- package/docs/snippets/tests/press-keys-replay.mdx +7 -0
- package/docs/snippets/tests/press-keys-yaml.mdx +36 -0
- package/docs/snippets/tests/remember-replay.mdx +7 -0
- package/docs/snippets/tests/remember-yaml.mdx +28 -0
- package/docs/snippets/tests/scroll-replay.mdx +7 -0
- package/docs/snippets/tests/scroll-until-image-replay.mdx +7 -0
- package/docs/snippets/tests/scroll-until-image-yaml.mdx +14 -0
- package/docs/snippets/tests/scroll-until-text-replay.mdx +7 -0
- package/docs/snippets/tests/scroll-until-text-yaml.mdx +17 -0
- package/docs/snippets/tests/scroll-yaml.mdx +30 -0
- package/docs/snippets/tests/type-repeated-replay.mdx +7 -0
- package/docs/snippets/tests/type-repeated-yaml.mdx +22 -0
- package/docs/snippets/tests/type-replay.mdx +7 -0
- package/docs/snippets/tests/type-yaml.mdx +28 -0
- package/docs/snippets/tests/wait-for-image-replay.mdx +7 -0
- package/docs/snippets/tests/wait-for-image-yaml.mdx +18 -0
- package/docs/snippets/tests/wait-for-text-replay.mdx +7 -0
- package/docs/snippets/tests/wait-for-text-yaml.mdx +18 -0
- package/docs/snippets/tests/wait-replay.mdx +7 -0
- package/docs/snippets/tests/wait-yaml.mdx +13 -0
- package/docs/styles.css +65 -0
- package/docs/v6/account/dashboard.mdx +16 -0
- package/docs/v6/account/enterprise.mdx +110 -0
- package/docs/v6/account/pricing.mdx +33 -0
- package/docs/v6/account/projects.mdx +33 -0
- package/docs/v6/account/team.mdx +35 -0
- package/docs/v6/action/ami.mdx +109 -0
- package/docs/v6/action/performance.mdx +105 -0
- package/docs/v6/action/secrets.mdx +93 -0
- package/docs/v6/apps/chrome-extensions.mdx +48 -0
- package/docs/v6/apps/desktop-apps.mdx +93 -0
- package/docs/v6/apps/mobile-apps.mdx +26 -0
- package/docs/v6/apps/static-websites.mdx +54 -0
- package/docs/v6/apps/tauri-apps.mdx +361 -0
- package/docs/v6/bugs/jira.mdx +232 -0
- package/docs/v6/cli/overview.mdx +66 -0
- package/docs/v6/commands/assert.mdx +45 -0
- package/docs/v6/commands/exec.mdx +276 -0
- package/docs/v6/commands/focus-application.mdx +44 -0
- package/docs/v6/commands/hover-image.mdx +69 -0
- package/docs/v6/commands/hover-text.mdx +47 -0
- package/docs/v6/commands/if.mdx +53 -0
- package/docs/v6/commands/match-image.mdx +67 -0
- package/docs/v6/commands/press-keys.mdx +87 -0
- package/docs/v6/commands/remember.mdx +49 -0
- package/docs/v6/commands/run.mdx +44 -0
- package/docs/v6/commands/scroll-until-image.mdx +66 -0
- package/docs/v6/commands/scroll-until-text.mdx +60 -0
- package/docs/v6/commands/scroll.mdx +69 -0
- package/docs/v6/commands/type.mdx +45 -0
- package/docs/v6/commands/wait-for-image.mdx +54 -0
- package/docs/v6/commands/wait-for-text.mdx +48 -0
- package/docs/v6/commands/wait.mdx +45 -0
- package/docs/v6/exporting/junit.mdx +218 -0
- package/docs/v6/exporting/playwright.mdx +197 -0
- package/docs/v6/features/auto-healing.mdx +144 -0
- package/docs/v6/features/generation.mdx +116 -0
- package/docs/v6/features/parallel-testing.mdx +151 -0
- package/docs/v6/features/reusable-snippets.mdx +131 -0
- package/docs/v6/features/selectorless.mdx +80 -0
- package/docs/v6/features/visual-assertions.mdx +139 -0
- package/docs/v6/getting-started/ci.mdx +146 -0
- package/docs/v6/getting-started/cli.mdx +91 -0
- package/docs/v6/getting-started/editing.mdx +100 -0
- package/docs/v6/getting-started/playwright.mdx +342 -0
- package/docs/v6/getting-started/running.mdx +48 -0
- package/docs/v6/getting-started/self-hosting.mdx +408 -0
- package/docs/v6/getting-started/vscode.mdx +88 -0
- package/docs/v6/guide/assertions.mdx +189 -0
- package/docs/v6/guide/authentication.mdx +136 -0
- package/docs/v6/guide/code.mdx +65 -0
- package/docs/v6/guide/dashcam.mdx +118 -0
- package/docs/v6/guide/environment-variables.mdx +26 -0
- package/docs/v6/guide/lifecycle.mdx +242 -0
- package/docs/v6/guide/locating.mdx +141 -0
- package/docs/v6/guide/protips.mdx +43 -0
- package/docs/v6/guide/variables.mdx +143 -0
- package/docs/v6/guide/waiting.mdx +130 -0
- package/docs/v6/importing/csv.mdx +196 -0
- package/docs/v6/importing/gherkin.mdx +143 -0
- package/docs/v6/importing/jira.mdx +164 -0
- package/docs/v6/importing/testrail.mdx +162 -0
- package/docs/v6/integrations/electron.mdx +146 -0
- package/docs/v6/integrations/netlify.mdx +100 -0
- package/docs/v6/integrations/vercel.mdx +125 -0
- package/docs/v6/interactive/explore.mdx +99 -0
- package/docs/v6/interactive/run.mdx +52 -0
- package/docs/v6/interactive/save.mdx +63 -0
- package/docs/v6/overview/comparison.mdx +101 -0
- package/docs/v6/overview/faq.mdx +162 -0
- package/docs/v6/overview/performance.mdx +52 -0
- package/docs/v6/overview/quickstart.mdx +137 -0
- package/docs/v6/overview/what-is-testdriver.mdx +85 -0
- package/docs/v6/scenarios/ai-chatbot.mdx +28 -0
- package/docs/v6/scenarios/cookie-banner.mdx +32 -0
- package/docs/v6/scenarios/file-upload.mdx +33 -0
- package/docs/v6/scenarios/form-filling.mdx +32 -0
- package/docs/v6/scenarios/log-in.mdx +75 -0
- package/docs/v6/scenarios/pdf-generation.mdx +25 -0
- package/docs/v6/scenarios/spell-check.mdx +22 -0
- package/docs/v6/security/action.mdx +84 -0
- package/docs/v6/security/agent.mdx +73 -0
- package/docs/v6/security/platform.mdx +77 -0
- package/docs/v6/tutorials/advanced-test.mdx +81 -0
- package/docs/v6/tutorials/basic-test.mdx +45 -0
- package/docs/v7/_drafts/agents.mdx +843 -0
- package/docs/v7/_drafts/architecture.mdx +399 -0
- package/docs/v7/_drafts/auto-cache-key.mdx +167 -0
- package/docs/v7/_drafts/awesome-logs-quick-ref.mdx +100 -0
- package/docs/v7/_drafts/best-practices.mdx +486 -0
- package/docs/v7/_drafts/caching-ai.mdx +215 -0
- package/docs/v7/_drafts/caching-selectors.mdx +424 -0
- package/docs/v7/_drafts/caching.mdx +366 -0
- package/docs/v7/_drafts/cli-to-sdk-migration.mdx +425 -0
- package/docs/v7/_drafts/commands/assert.mdx +45 -0
- package/docs/v7/_drafts/commands/exec.mdx +276 -0
- package/docs/v7/_drafts/commands/focus-application.mdx +44 -0
- package/docs/v7/_drafts/commands/hover-image.mdx +69 -0
- package/docs/v7/_drafts/commands/hover-text.mdx +47 -0
- package/docs/v7/_drafts/commands/if.mdx +53 -0
- package/docs/v7/_drafts/commands/match-image.mdx +67 -0
- package/docs/v7/_drafts/commands/press-keys.mdx +87 -0
- package/docs/v7/_drafts/commands/remember.mdx +49 -0
- package/docs/v7/_drafts/commands/run.mdx +44 -0
- package/docs/v7/_drafts/commands/scroll-until-image.mdx +66 -0
- package/docs/v7/_drafts/commands/scroll-until-text.mdx +60 -0
- package/docs/v7/_drafts/commands/scroll.mdx +69 -0
- package/docs/v7/_drafts/commands/type.mdx +45 -0
- package/docs/v7/_drafts/commands/wait-for-image.mdx +54 -0
- package/docs/v7/_drafts/commands/wait-for-text.mdx +48 -0
- package/docs/v7/_drafts/commands/wait.mdx +45 -0
- package/docs/v7/_drafts/configuration.mdx +378 -0
- package/docs/v7/_drafts/contributing.mdx +174 -0
- package/docs/v7/_drafts/core.mdx +458 -0
- package/docs/v7/_drafts/dashcam-title-feature.mdx +89 -0
- package/docs/v7/_drafts/debugging.mdx +349 -0
- package/docs/v7/_drafts/error-handling.mdx +501 -0
- package/docs/v7/_drafts/faq.mdx +393 -0
- package/docs/v7/_drafts/hooks.mdx +360 -0
- package/docs/v7/_drafts/init-command.mdx +95 -0
- package/docs/v7/_drafts/installation.mdx +420 -0
- package/docs/v7/_drafts/migration.mdx +562 -0
- package/docs/v7/_drafts/observable.mdx +604 -0
- package/docs/v7/_drafts/playwright.mdx +342 -0
- package/docs/v7/_drafts/plugin-migration.mdx +220 -0
- package/docs/v7/_drafts/powerful.mdx +419 -0
- package/docs/v7/_drafts/presets.mdx +210 -0
- package/docs/v7/_drafts/progressive-disclosure.mdx +230 -0
- package/docs/v7/_drafts/prompt-cache.mdx +200 -0
- package/docs/v7/_drafts/provision.mdx +390 -0
- package/docs/v7/_drafts/quick-start-test-recording.mdx +214 -0
- package/docs/v7/_drafts/readme.mdx +135 -0
- package/docs/v7/_drafts/reports.mdx +414 -0
- package/docs/v7/_drafts/scalable.mdx +763 -0
- package/docs/v7/_drafts/screenshot.mdx +155 -0
- package/docs/v7/_drafts/sdk-awesome-logs.mdx +468 -0
- package/docs/v7/_drafts/sdk-browser-rendering.mdx +167 -0
- package/docs/v7/_drafts/sdk-migration.mdx +474 -0
- package/docs/v7/_drafts/sdk-v7-complete.mdx +345 -0
- package/docs/v7/_drafts/self-hosting.mdx +369 -0
- package/docs/v7/_drafts/test-recording.mdx +382 -0
- package/docs/v7/_drafts/troubleshooting.mdx +526 -0
- package/docs/v7/_drafts/vitest-plugin.mdx +477 -0
- package/docs/v7/_drafts/vitest.mdx +535 -0
- package/docs/v7/_drafts/writing-tests.mdx +25 -0
- package/docs/v7/ai.mdx +205 -0
- package/docs/v7/assert.mdx +316 -0
- package/docs/v7/aws-setup.mdx +449 -0
- package/docs/v7/cache.mdx +223 -0
- package/docs/v7/caching.mdx +128 -0
- package/docs/v7/captcha.mdx +159 -0
- package/docs/v7/ci-cd.mdx +603 -0
- package/docs/v7/click.mdx +287 -0
- package/docs/v7/client.mdx +478 -0
- package/docs/v7/copilot/auto-healing.mdx +265 -0
- package/docs/v7/copilot/creating-tests.mdx +156 -0
- package/docs/v7/copilot/github.mdx +143 -0
- package/docs/v7/copilot/running-tests.mdx +149 -0
- package/docs/v7/copilot/setup.mdx +143 -0
- package/docs/v7/customizing-devices.mdx +319 -0
- package/docs/v7/dashcam.mdx +419 -0
- package/docs/v7/debugging-with-screenshots.mdx +402 -0
- package/docs/v7/device-config.mdx +317 -0
- package/docs/v7/double-click.mdx +102 -0
- package/docs/v7/elements.mdx +606 -0
- package/docs/v7/enterprise.mdx +9 -0
- package/docs/v7/errors.mdx +248 -0
- package/docs/v7/events.mdx +358 -0
- package/docs/v7/examples/ai.mdx +72 -0
- package/docs/v7/examples/assert.mdx +72 -0
- package/docs/v7/examples/captcha-api.mdx +92 -0
- package/docs/v7/examples/chrome-extension.mdx +132 -0
- package/docs/v7/examples/drag-and-drop.mdx +100 -0
- package/docs/v7/examples/element-not-found.mdx +67 -0
- package/docs/v7/examples/exec-output.mdx +85 -0
- package/docs/v7/examples/exec-pwsh.mdx +83 -0
- package/docs/v7/examples/focus-window.mdx +62 -0
- package/docs/v7/examples/hover-image.mdx +94 -0
- package/docs/v7/examples/hover-text.mdx +69 -0
- package/docs/v7/examples/installer.mdx +91 -0
- package/docs/v7/examples/launch-vscode-linux.mdx +101 -0
- package/docs/v7/examples/match-image.mdx +96 -0
- package/docs/v7/examples/press-keys.mdx +92 -0
- package/docs/v7/examples/scroll-keyboard.mdx +79 -0
- package/docs/v7/examples/scroll-until-image.mdx +81 -0
- package/docs/v7/examples/scroll-until-text.mdx +109 -0
- package/docs/v7/examples/scroll.mdx +81 -0
- package/docs/v7/examples/type.mdx +92 -0
- package/docs/v7/examples/windows-installer.mdx +89 -0
- package/docs/v7/exec.mdx +318 -0
- package/docs/v7/find.mdx +830 -0
- package/docs/v7/focus-application.mdx +294 -0
- package/docs/v7/generating-tests.mdx +36 -0
- package/docs/v7/hosted.mdx +158 -0
- package/docs/v7/hover.mdx +279 -0
- package/docs/v7/locating-elements.mdx +71 -0
- package/docs/v7/making-assertions.mdx +32 -0
- package/docs/v7/mcp.mdx +9 -0
- package/docs/v7/mouse-down.mdx +161 -0
- package/docs/v7/mouse-up.mdx +164 -0
- package/docs/v7/parse.mdx +237 -0
- package/docs/v7/performing-actions.mdx +54 -0
- package/docs/v7/press-keys.mdx +349 -0
- package/docs/v7/provision.mdx +333 -0
- package/docs/v7/quickstart.mdx +173 -0
- package/docs/v7/redraw.mdx +216 -0
- package/docs/v7/reusable-code.mdx +249 -0
- package/docs/v7/right-click.mdx +123 -0
- package/docs/v7/running-tests.mdx +185 -0
- package/docs/v7/screenshot.mdx +249 -0
- package/docs/v7/screenshots.mdx +186 -0
- package/docs/v7/scroll.mdx +336 -0
- package/docs/v7/secrets.mdx +115 -0
- package/docs/v7/self-hosted.mdx +149 -0
- package/docs/v7/type.mdx +358 -0
- package/docs/v7/variables.mdx +111 -0
- package/docs/v7/wait.mdx +52 -0
- package/docs/v7/waiting-for-elements.mdx +90 -0
- package/docs/v7/what-is-testdriver.mdx +54 -0
- package/eslint.config.js +67 -0
- package/examples/ai.test.mjs +31 -0
- package/examples/assert.test.mjs +47 -0
- package/examples/chrome-extension.test.mjs +97 -0
- package/examples/config.mjs +5 -0
- package/examples/element-not-found.test.mjs +27 -0
- package/examples/exec-output.test.mjs +60 -0
- package/examples/exec-pwsh.test.mjs +58 -0
- package/examples/findall-coffee-icons.test.mjs +42 -0
- package/examples/focus-window.test.mjs +37 -0
- package/examples/formatted-logging.test.mjs +27 -0
- package/examples/hover-image.test.mjs +53 -0
- package/examples/hover-text-with-description.test.mjs +57 -0
- package/examples/hover-text.test.mjs +28 -0
- package/examples/installer.test.mjs +50 -0
- package/examples/launch-vscode-linux.test.mjs +55 -0
- package/examples/match-image.test.mjs +55 -0
- package/examples/parse.test.mjs +19 -0
- package/examples/press-keys.test.mjs +44 -0
- package/examples/prompt.test.mjs +34 -0
- package/examples/scroll-keyboard.test.mjs +38 -0
- package/examples/scroll-until-image.test.mjs +40 -0
- package/examples/scroll.test.mjs +42 -0
- package/examples/type.test.mjs +46 -0
- package/examples/windows-installer.test.mjs +54 -0
- package/index.js +2 -0
- package/interfaces/cli/commands/init.js +438 -0
- package/interfaces/cli/commands/setup.js +382 -0
- package/interfaces/cli/lib/base.js +285 -0
- package/interfaces/cli.js +20 -0
- package/interfaces/junit-reporter.js +290 -0
- package/interfaces/logger.js +388 -0
- package/interfaces/readline.js +234 -0
- package/interfaces/shared-test-state.mjs +64 -0
- package/interfaces/vitest-plugin.d.ts +115 -0
- package/interfaces/vitest-plugin.mjs +1698 -0
- package/lib/captcha/solver.js +358 -0
- package/lib/core/Dashcam.js +533 -0
- package/lib/core/index.d.ts +172 -0
- package/lib/core/index.js +12 -0
- package/lib/environments.json +18 -0
- package/lib/github-comment-formatter.js +263 -0
- package/lib/github-comment.mjs +452 -0
- package/lib/init-project.js +575 -0
- package/lib/presets/index.mjs +331 -0
- package/lib/resolve-channel.js +46 -0
- package/lib/sentry.js +417 -0
- package/lib/vitest/hooks.d.ts +57 -0
- package/lib/vitest/hooks.mjs +674 -0
- package/lib/vitest/setup-aws.mjs +247 -0
- package/lib/vitest/setup-self-hosted.mjs +151 -0
- package/lib/vitest/setup.mjs +46 -0
- package/manual/captcha-api.test.mjs +51 -0
- package/manual/drag-and-drop.test.mjs +59 -0
- package/manual/flake-diffthreshold-001.test.mjs +9 -0
- package/manual/flake-diffthreshold-01.test.mjs +9 -0
- package/manual/flake-diffthreshold-05.test.mjs +9 -0
- package/manual/flake-noredraw-cache.test.mjs +9 -0
- package/manual/flake-noredraw-nocache.test.mjs +9 -0
- package/manual/flake-redraw-cache.test.mjs +9 -0
- package/manual/flake-redraw-nocache.test.mjs +9 -0
- package/manual/flake-rocket-match.test.mjs +30 -0
- package/manual/flake-shared.mjs +51 -0
- package/manual/no-provision.test.mjs +31 -0
- package/manual/packer-hover-image.test.mjs +176 -0
- package/manual/scroll-until-text.test.mjs +68 -0
- package/manual/test-init-command.js +223 -0
- package/mcp-server/README.md +322 -0
- package/mcp-server/dist/codegen.d.ts +9 -0
- package/mcp-server/dist/codegen.js +165 -0
- package/mcp-server/dist/mcp-app.html +114 -0
- package/mcp-server/dist/package.json +1 -0
- package/mcp-server/dist/provision-types.d.ts +290 -0
- package/mcp-server/dist/provision-types.js +174 -0
- package/mcp-server/dist/server.d.ts +6 -0
- package/mcp-server/dist/server.mjs +1925 -0
- package/mcp-server/dist/session.d.ts +85 -0
- package/mcp-server/dist/session.js +152 -0
- package/mcp-server/mcp-app.html +28 -0
- package/mcp-server/mcp-config.example.json +19 -0
- package/mcp-server/package-lock.json +4027 -0
- package/mcp-server/package.json +31 -0
- package/mcp-server/src/codegen.ts +189 -0
- package/mcp-server/src/mcp-app.css +360 -0
- package/mcp-server/src/mcp-app.ts +547 -0
- package/mcp-server/src/provision-types.ts +209 -0
- package/mcp-server/src/server.ts +2391 -0
- package/mcp-server/src/session.ts +194 -0
- package/mcp-server/tsconfig.json +16 -0
- package/mcp-server/vite.config.ts +23 -0
- package/package.json +158 -0
- package/schema.json +1046 -0
- package/scripts/generate-skills.js +94 -0
- package/sdk-log-formatter.js +1157 -0
- package/sdk.d.ts +1486 -0
- package/sdk.js +4336 -0
- package/setup/aws/cloudformation.yaml +463 -0
- package/setup/aws/disable-defender.sh +42 -0
- package/setup/aws/install-dev-runner.sh +79 -0
- package/setup/aws/spawn-runner.sh +289 -0
- package/test/captcha-solver.test.mjs +152 -0
- package/test/chrome-remote-debugging.test.mjs +66 -0
- package/test/duckduckgo/experiment.test.mjs +28 -0
- package/test/duckduckgo/setup.test.mjs +29 -0
- package/test/manual/debug-locate-response.js +82 -0
- package/test/manual/reconnect-provision.test.mjs +49 -0
- package/test/manual/test-console-logs.test.mjs +42 -0
- package/test/manual/test-find-api.js +73 -0
- package/test/manual/test-init.sh +54 -0
- package/test/manual/test-prompt-cache.js +97 -0
- package/test/manual/test-provision-auth.mjs +22 -0
- package/test/manual/test-sandbox-render.js +29 -0
- package/test/manual/test-sdk-methods.js +15 -0
- package/test/manual/test-sdk-refactor.js +53 -0
- package/test/manual/test-stack-trace.mjs +57 -0
- package/test/manual/verify-element-api.js +89 -0
- package/test/manual/verify-types.js +0 -0
- package/test/manual-unawaited-promise.test.mjs +31 -0
- package/vitest.config.mjs +58 -0
- package/vitest.runner.config.mjs +33 -0
- package/vscode-extension/.vscodeignore +12 -0
- package/vscode-extension/README.md +94 -0
- package/vscode-extension/media/icon.png +0 -0
- package/vscode-extension/package-lock.json +4126 -0
- package/vscode-extension/package.json +86 -0
- package/vscode-extension/src/extension.ts +829 -0
- package/vscode-extension/testdriverai-0.1.0.vsix +0 -0
- 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
|
+
};
|