devharness 0.8.0
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/LICENSE +21 -0
- package/README.md +185 -0
- package/build/atomic-write.d.ts +28 -0
- package/build/atomic-write.d.ts.map +1 -0
- package/build/atomic-write.js +126 -0
- package/build/atomic-write.js.map +1 -0
- package/build/cdp-manager.d.ts +524 -0
- package/build/cdp-manager.d.ts.map +1 -0
- package/build/cdp-manager.js +1828 -0
- package/build/cdp-manager.js.map +1 -0
- package/build/cdp-manager.test.d.ts +6 -0
- package/build/cdp-manager.test.d.ts.map +1 -0
- package/build/cdp-manager.test.js +546 -0
- package/build/cdp-manager.test.js.map +1 -0
- package/build/chrome-launcher.d.ts +400 -0
- package/build/chrome-launcher.d.ts.map +1 -0
- package/build/chrome-launcher.js +1071 -0
- package/build/chrome-launcher.js.map +1 -0
- package/build/chrome-launcher.test.d.ts +11 -0
- package/build/chrome-launcher.test.d.ts.map +1 -0
- package/build/chrome-launcher.test.js +204 -0
- package/build/chrome-launcher.test.js.map +1 -0
- package/build/clickable-cache.d.ts +73 -0
- package/build/clickable-cache.d.ts.map +1 -0
- package/build/clickable-cache.js +90 -0
- package/build/clickable-cache.js.map +1 -0
- package/build/command-recorder.d.ts +401 -0
- package/build/command-recorder.d.ts.map +1 -0
- package/build/command-recorder.js +701 -0
- package/build/command-recorder.js.map +1 -0
- package/build/config.d.ts +390 -0
- package/build/config.d.ts.map +1 -0
- package/build/config.js +826 -0
- package/build/config.js.map +1 -0
- package/build/config.test.d.ts +2 -0
- package/build/config.test.d.ts.map +1 -0
- package/build/config.test.js +112 -0
- package/build/config.test.js.map +1 -0
- package/build/connection-manager.d.ts +159 -0
- package/build/connection-manager.d.ts.map +1 -0
- package/build/connection-manager.js +432 -0
- package/build/connection-manager.js.map +1 -0
- package/build/connection-manager.test.d.ts +11 -0
- package/build/connection-manager.test.d.ts.map +1 -0
- package/build/connection-manager.test.js +114 -0
- package/build/connection-manager.test.js.map +1 -0
- package/build/console-monitor.d.ts +150 -0
- package/build/console-monitor.d.ts.map +1 -0
- package/build/console-monitor.js +454 -0
- package/build/console-monitor.js.map +1 -0
- package/build/dashboard/bundle.js +1 -0
- package/build/dashboard/dashboard-client.d.ts +42 -0
- package/build/dashboard/dashboard-client.d.ts.map +1 -0
- package/build/dashboard/dashboard-client.js +184 -0
- package/build/dashboard/dashboard-client.js.map +1 -0
- package/build/dashboard/dashboard-hub.d.ts +50 -0
- package/build/dashboard/dashboard-hub.d.ts.map +1 -0
- package/build/dashboard/dashboard-hub.js +654 -0
- package/build/dashboard/dashboard-hub.js.map +1 -0
- package/build/dashboard/hub-lock.d.ts +16 -0
- package/build/dashboard/hub-lock.d.ts.map +1 -0
- package/build/dashboard/hub-lock.js +77 -0
- package/build/dashboard/hub-lock.js.map +1 -0
- package/build/dashboard/index.d.ts +25 -0
- package/build/dashboard/index.d.ts.map +1 -0
- package/build/dashboard/index.js +77 -0
- package/build/dashboard/index.js.map +1 -0
- package/build/dashboard/types.d.ts +83 -0
- package/build/dashboard/types.d.ts.map +1 -0
- package/build/dashboard/types.js +6 -0
- package/build/dashboard/types.js.map +1 -0
- package/build/debug-logger.d.ts +85 -0
- package/build/debug-logger.d.ts.map +1 -0
- package/build/debug-logger.js +195 -0
- package/build/debug-logger.js.map +1 -0
- package/build/debugger-aware-wrapper.d.ts +37 -0
- package/build/debugger-aware-wrapper.d.ts.map +1 -0
- package/build/debugger-aware-wrapper.js +128 -0
- package/build/debugger-aware-wrapper.js.map +1 -0
- package/build/dom-change-monitor.d.ts +92 -0
- package/build/dom-change-monitor.d.ts.map +1 -0
- package/build/dom-change-monitor.js +437 -0
- package/build/dom-change-monitor.js.map +1 -0
- package/build/element-collector.d.ts +16 -0
- package/build/element-collector.d.ts.map +1 -0
- package/build/element-collector.js +207 -0
- package/build/element-collector.js.map +1 -0
- package/build/error-helpers.d.ts +43 -0
- package/build/error-helpers.d.ts.map +1 -0
- package/build/error-helpers.js +143 -0
- package/build/error-helpers.js.map +1 -0
- package/build/formatters/console-formatter.d.ts +160 -0
- package/build/formatters/console-formatter.d.ts.map +1 -0
- package/build/formatters/console-formatter.js +338 -0
- package/build/formatters/console-formatter.js.map +1 -0
- package/build/helpers/parser-plugins.d.ts +44 -0
- package/build/helpers/parser-plugins.d.ts.map +1 -0
- package/build/helpers/parser-plugins.js +102 -0
- package/build/helpers/parser-plugins.js.map +1 -0
- package/build/helpers/paths.d.ts +79 -0
- package/build/helpers/paths.d.ts.map +1 -0
- package/build/helpers/paths.js +168 -0
- package/build/helpers/paths.js.map +1 -0
- package/build/helpers/process-liveness.d.ts +24 -0
- package/build/helpers/process-liveness.d.ts.map +1 -0
- package/build/helpers/process-liveness.js +36 -0
- package/build/helpers/process-liveness.js.map +1 -0
- package/build/helpers/process-liveness.test.d.ts +2 -0
- package/build/helpers/process-liveness.test.d.ts.map +1 -0
- package/build/helpers/process-liveness.test.js +40 -0
- package/build/helpers/process-liveness.test.js.map +1 -0
- package/build/helpers/sequence-tree.d.ts +27 -0
- package/build/helpers/sequence-tree.d.ts.map +1 -0
- package/build/helpers/sequence-tree.js +80 -0
- package/build/helpers/sequence-tree.js.map +1 -0
- package/build/helpers/sequence-tree.test.d.ts +2 -0
- package/build/helpers/sequence-tree.test.d.ts.map +1 -0
- package/build/helpers/sequence-tree.test.js +122 -0
- package/build/helpers/sequence-tree.test.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +2007 -0
- package/build/index.js.map +1 -0
- package/build/interaction-recorder.d.ts +214 -0
- package/build/interaction-recorder.d.ts.map +1 -0
- package/build/interaction-recorder.js +2007 -0
- package/build/interaction-recorder.js.map +1 -0
- package/build/issue-tracker.d.ts +107 -0
- package/build/issue-tracker.d.ts.map +1 -0
- package/build/issue-tracker.js +582 -0
- package/build/issue-tracker.js.map +1 -0
- package/build/issue-tracker.test.d.ts +2 -0
- package/build/issue-tracker.test.d.ts.map +1 -0
- package/build/issue-tracker.test.js +88 -0
- package/build/issue-tracker.test.js.map +1 -0
- package/build/launch-chrome-port.test.d.ts +14 -0
- package/build/launch-chrome-port.test.d.ts.map +1 -0
- package/build/launch-chrome-port.test.js +97 -0
- package/build/launch-chrome-port.test.js.map +1 -0
- package/build/log-processor/orchestrator.d.ts +32 -0
- package/build/log-processor/orchestrator.d.ts.map +1 -0
- package/build/log-processor/orchestrator.js +27 -0
- package/build/log-processor/orchestrator.js.map +1 -0
- package/build/logpoint-execution-tracker.d.ts +57 -0
- package/build/logpoint-execution-tracker.d.ts.map +1 -0
- package/build/logpoint-execution-tracker.js +112 -0
- package/build/logpoint-execution-tracker.js.map +1 -0
- package/build/mcp-supervisor.d.ts +3 -0
- package/build/mcp-supervisor.d.ts.map +1 -0
- package/build/mcp-supervisor.js +211 -0
- package/build/mcp-supervisor.js.map +1 -0
- package/build/messages.d.ts +165 -0
- package/build/messages.d.ts.map +1 -0
- package/build/messages.js +574 -0
- package/build/messages.js.map +1 -0
- package/build/network-monitor.d.ts +172 -0
- package/build/network-monitor.d.ts.map +1 -0
- package/build/network-monitor.js +350 -0
- package/build/network-monitor.js.map +1 -0
- package/build/overlays.d.ts +49 -0
- package/build/overlays.d.ts.map +1 -0
- package/build/overlays.js +409 -0
- package/build/overlays.js.map +1 -0
- package/build/persistent-profiles.test.d.ts +15 -0
- package/build/persistent-profiles.test.d.ts.map +1 -0
- package/build/persistent-profiles.test.js +470 -0
- package/build/persistent-profiles.test.js.map +1 -0
- package/build/port-reserver.d.ts +32 -0
- package/build/port-reserver.d.ts.map +1 -0
- package/build/port-reserver.js +118 -0
- package/build/port-reserver.js.map +1 -0
- package/build/puppeteer-manager.d.ts +47 -0
- package/build/puppeteer-manager.d.ts.map +1 -0
- package/build/puppeteer-manager.js +116 -0
- package/build/puppeteer-manager.js.map +1 -0
- package/build/recording-coverage.test.d.ts +12 -0
- package/build/recording-coverage.test.d.ts.map +1 -0
- package/build/recording-coverage.test.js +72 -0
- package/build/recording-coverage.test.js.map +1 -0
- package/build/reference-validator.d.ts +47 -0
- package/build/reference-validator.d.ts.map +1 -0
- package/build/reference-validator.js +86 -0
- package/build/reference-validator.js.map +1 -0
- package/build/reference-validator.test.d.ts +5 -0
- package/build/reference-validator.test.d.ts.map +1 -0
- package/build/reference-validator.test.js +243 -0
- package/build/reference-validator.test.js.map +1 -0
- package/build/replay-cursor.d.ts +27 -0
- package/build/replay-cursor.d.ts.map +1 -0
- package/build/replay-cursor.js +240 -0
- package/build/replay-cursor.js.map +1 -0
- package/build/runners/docker-compose-runner.d.ts +69 -0
- package/build/runners/docker-compose-runner.d.ts.map +1 -0
- package/build/runners/docker-compose-runner.js +438 -0
- package/build/runners/docker-compose-runner.js.map +1 -0
- package/build/runners/docker-runner.d.ts +65 -0
- package/build/runners/docker-runner.d.ts.map +1 -0
- package/build/runners/docker-runner.js +414 -0
- package/build/runners/docker-runner.js.map +1 -0
- package/build/runners/index.d.ts +19 -0
- package/build/runners/index.d.ts.map +1 -0
- package/build/runners/index.js +35 -0
- package/build/runners/index.js.map +1 -0
- package/build/runners/native-runner.d.ts +95 -0
- package/build/runners/native-runner.d.ts.map +1 -0
- package/build/runners/native-runner.js +370 -0
- package/build/runners/native-runner.js.map +1 -0
- package/build/runners/types.d.ts +147 -0
- package/build/runners/types.d.ts.map +1 -0
- package/build/runners/types.js +25 -0
- package/build/runners/types.js.map +1 -0
- package/build/self-restart.d.ts +12 -0
- package/build/self-restart.d.ts.map +1 -0
- package/build/self-restart.js +41 -0
- package/build/self-restart.js.map +1 -0
- package/build/self-restart.test.d.ts +2 -0
- package/build/self-restart.test.d.ts.map +1 -0
- package/build/self-restart.test.js +34 -0
- package/build/self-restart.test.js.map +1 -0
- package/build/server-claims.d.ts +161 -0
- package/build/server-claims.d.ts.map +1 -0
- package/build/server-claims.js +382 -0
- package/build/server-claims.js.map +1 -0
- package/build/server-claims.test.d.ts +2 -0
- package/build/server-claims.test.d.ts.map +1 -0
- package/build/server-claims.test.js +197 -0
- package/build/server-claims.test.js.map +1 -0
- package/build/server-manager.d.ts +438 -0
- package/build/server-manager.d.ts.map +1 -0
- package/build/server-manager.js +1674 -0
- package/build/server-manager.js.map +1 -0
- package/build/server-manager.test.d.ts +17 -0
- package/build/server-manager.test.d.ts.map +1 -0
- package/build/server-manager.test.js +122 -0
- package/build/server-manager.test.js.map +1 -0
- package/build/server-ownership.test.d.ts +2 -0
- package/build/server-ownership.test.d.ts.map +1 -0
- package/build/server-ownership.test.js +238 -0
- package/build/server-ownership.test.js.map +1 -0
- package/build/server-watcher.d.ts +21 -0
- package/build/server-watcher.d.ts.map +1 -0
- package/build/server-watcher.js +105 -0
- package/build/server-watcher.js.map +1 -0
- package/build/session-detector.d.ts +47 -0
- package/build/session-detector.d.ts.map +1 -0
- package/build/session-detector.js +229 -0
- package/build/session-detector.js.map +1 -0
- package/build/session-detector.test.d.ts +9 -0
- package/build/session-detector.test.d.ts.map +1 -0
- package/build/session-detector.test.js +45 -0
- package/build/session-detector.test.js.map +1 -0
- package/build/sourcemap-handler.d.ts +114 -0
- package/build/sourcemap-handler.d.ts.map +1 -0
- package/build/sourcemap-handler.js +479 -0
- package/build/sourcemap-handler.js.map +1 -0
- package/build/supervisor/child-manager.d.ts +43 -0
- package/build/supervisor/child-manager.d.ts.map +1 -0
- package/build/supervisor/child-manager.js +148 -0
- package/build/supervisor/child-manager.js.map +1 -0
- package/build/supervisor/child-manager.test.d.ts +2 -0
- package/build/supervisor/child-manager.test.d.ts.map +1 -0
- package/build/supervisor/child-manager.test.js +107 -0
- package/build/supervisor/child-manager.test.js.map +1 -0
- package/build/supervisor/client-watcher.d.ts +48 -0
- package/build/supervisor/client-watcher.d.ts.map +1 -0
- package/build/supervisor/client-watcher.js +186 -0
- package/build/supervisor/client-watcher.js.map +1 -0
- package/build/supervisor/client-watcher.test.d.ts +2 -0
- package/build/supervisor/client-watcher.test.d.ts.map +1 -0
- package/build/supervisor/client-watcher.test.js +121 -0
- package/build/supervisor/client-watcher.test.js.map +1 -0
- package/build/supervisor/idle-config.d.ts +30 -0
- package/build/supervisor/idle-config.d.ts.map +1 -0
- package/build/supervisor/idle-config.js +76 -0
- package/build/supervisor/idle-config.js.map +1 -0
- package/build/supervisor/idle-config.test.d.ts +2 -0
- package/build/supervisor/idle-config.test.d.ts.map +1 -0
- package/build/supervisor/idle-config.test.js +119 -0
- package/build/supervisor/idle-config.test.js.map +1 -0
- package/build/supervisor/ndjson-reader.d.ts +47 -0
- package/build/supervisor/ndjson-reader.d.ts.map +1 -0
- package/build/supervisor/ndjson-reader.js +75 -0
- package/build/supervisor/ndjson-reader.js.map +1 -0
- package/build/supervisor/ndjson-reader.test.d.ts +2 -0
- package/build/supervisor/ndjson-reader.test.d.ts.map +1 -0
- package/build/supervisor/ndjson-reader.test.js +92 -0
- package/build/supervisor/ndjson-reader.test.js.map +1 -0
- package/build/supervisor/pidfile.d.ts +11 -0
- package/build/supervisor/pidfile.d.ts.map +1 -0
- package/build/supervisor/pidfile.js +29 -0
- package/build/supervisor/pidfile.js.map +1 -0
- package/build/supervisor/pidfile.test.d.ts +8 -0
- package/build/supervisor/pidfile.test.d.ts.map +1 -0
- package/build/supervisor/pidfile.test.js +46 -0
- package/build/supervisor/pidfile.test.js.map +1 -0
- package/build/supervisor/restart-coordinator.d.ts +73 -0
- package/build/supervisor/restart-coordinator.d.ts.map +1 -0
- package/build/supervisor/restart-coordinator.js +300 -0
- package/build/supervisor/restart-coordinator.js.map +1 -0
- package/build/supervisor/restart-coordinator.test.d.ts +2 -0
- package/build/supervisor/restart-coordinator.test.d.ts.map +1 -0
- package/build/supervisor/restart-coordinator.test.js +434 -0
- package/build/supervisor/restart-coordinator.test.js.map +1 -0
- package/build/test-support/fake-execute-tool-call.d.ts +11 -0
- package/build/test-support/fake-execute-tool-call.d.ts.map +1 -0
- package/build/test-support/fake-execute-tool-call.js +19 -0
- package/build/test-support/fake-execute-tool-call.js.map +1 -0
- package/build/tool-error.d.ts +14 -0
- package/build/tool-error.d.ts.map +1 -0
- package/build/tool-error.js +18 -0
- package/build/tool-error.js.map +1 -0
- package/build/tool-response.d.ts +293 -0
- package/build/tool-response.d.ts.map +1 -0
- package/build/tool-response.js +365 -0
- package/build/tool-response.js.map +1 -0
- package/build/tools/assert-tools.d.ts +62 -0
- package/build/tools/assert-tools.d.ts.map +1 -0
- package/build/tools/assert-tools.js +330 -0
- package/build/tools/assert-tools.js.map +1 -0
- package/build/tools/breakpoint-await-abort.test.d.ts +2 -0
- package/build/tools/breakpoint-await-abort.test.d.ts.map +1 -0
- package/build/tools/breakpoint-await-abort.test.js +124 -0
- package/build/tools/breakpoint-await-abort.test.js.map +1 -0
- package/build/tools/breakpoint-tools.d.ts +99 -0
- package/build/tools/breakpoint-tools.d.ts.map +1 -0
- package/build/tools/breakpoint-tools.js +1197 -0
- package/build/tools/breakpoint-tools.js.map +1 -0
- package/build/tools/config-tools.d.ts +58 -0
- package/build/tools/config-tools.d.ts.map +1 -0
- package/build/tools/config-tools.js +180 -0
- package/build/tools/config-tools.js.map +1 -0
- package/build/tools/connection-routing.test.d.ts +12 -0
- package/build/tools/connection-routing.test.d.ts.map +1 -0
- package/build/tools/connection-routing.test.js +206 -0
- package/build/tools/connection-routing.test.js.map +1 -0
- package/build/tools/console-tools.d.ts +84 -0
- package/build/tools/console-tools.d.ts.map +1 -0
- package/build/tools/console-tools.js +241 -0
- package/build/tools/console-tools.js.map +1 -0
- package/build/tools/content-tools.d.ts +74 -0
- package/build/tools/content-tools.d.ts.map +1 -0
- package/build/tools/content-tools.js +582 -0
- package/build/tools/content-tools.js.map +1 -0
- package/build/tools/dashboard-tools.d.ts +38 -0
- package/build/tools/dashboard-tools.d.ts.map +1 -0
- package/build/tools/dashboard-tools.js +123 -0
- package/build/tools/dashboard-tools.js.map +1 -0
- package/build/tools/dom-tools.d.ts +41 -0
- package/build/tools/dom-tools.d.ts.map +1 -0
- package/build/tools/dom-tools.js +277 -0
- package/build/tools/dom-tools.js.map +1 -0
- package/build/tools/download-tools.d.ts +55 -0
- package/build/tools/download-tools.d.ts.map +1 -0
- package/build/tools/download-tools.js +280 -0
- package/build/tools/download-tools.js.map +1 -0
- package/build/tools/execution-tools.d.ts +40 -0
- package/build/tools/execution-tools.d.ts.map +1 -0
- package/build/tools/execution-tools.js +121 -0
- package/build/tools/execution-tools.js.map +1 -0
- package/build/tools/input-abort.test.d.ts +2 -0
- package/build/tools/input-abort.test.d.ts.map +1 -0
- package/build/tools/input-abort.test.js +227 -0
- package/build/tools/input-abort.test.js.map +1 -0
- package/build/tools/input-ambiguous-selector.test.d.ts +2 -0
- package/build/tools/input-ambiguous-selector.test.d.ts.map +1 -0
- package/build/tools/input-ambiguous-selector.test.js +34 -0
- package/build/tools/input-ambiguous-selector.test.js.map +1 -0
- package/build/tools/input-tools.d.ts +168 -0
- package/build/tools/input-tools.d.ts.map +1 -0
- package/build/tools/input-tools.js +1397 -0
- package/build/tools/input-tools.js.map +1 -0
- package/build/tools/inspection-tools.d.ts +112 -0
- package/build/tools/inspection-tools.d.ts.map +1 -0
- package/build/tools/inspection-tools.js +637 -0
- package/build/tools/inspection-tools.js.map +1 -0
- package/build/tools/interpolation.d.ts +30 -0
- package/build/tools/interpolation.d.ts.map +1 -0
- package/build/tools/interpolation.js +143 -0
- package/build/tools/interpolation.js.map +1 -0
- package/build/tools/issues-abort-hygiene.test.d.ts +2 -0
- package/build/tools/issues-abort-hygiene.test.d.ts.map +1 -0
- package/build/tools/issues-abort-hygiene.test.js +79 -0
- package/build/tools/issues-abort-hygiene.test.js.map +1 -0
- package/build/tools/issues-tools.d.ts +98 -0
- package/build/tools/issues-tools.d.ts.map +1 -0
- package/build/tools/issues-tools.js +821 -0
- package/build/tools/issues-tools.js.map +1 -0
- package/build/tools/issues-tools.test.d.ts +8 -0
- package/build/tools/issues-tools.test.d.ts.map +1 -0
- package/build/tools/issues-tools.test.js +184 -0
- package/build/tools/issues-tools.test.js.map +1 -0
- package/build/tools/modal-tools.d.ts +73 -0
- package/build/tools/modal-tools.d.ts.map +1 -0
- package/build/tools/modal-tools.js +161 -0
- package/build/tools/modal-tools.js.map +1 -0
- package/build/tools/network-tools.d.ts +72 -0
- package/build/tools/network-tools.d.ts.map +1 -0
- package/build/tools/network-tools.js +432 -0
- package/build/tools/network-tools.js.map +1 -0
- package/build/tools/page-tools.d.ts +78 -0
- package/build/tools/page-tools.d.ts.map +1 -0
- package/build/tools/page-tools.js +255 -0
- package/build/tools/page-tools.js.map +1 -0
- package/build/tools/plugin-tools.d.ts +16 -0
- package/build/tools/plugin-tools.d.ts.map +1 -0
- package/build/tools/plugin-tools.js +17 -0
- package/build/tools/plugin-tools.js.map +1 -0
- package/build/tools/replay-abort.test.d.ts +2 -0
- package/build/tools/replay-abort.test.d.ts.map +1 -0
- package/build/tools/replay-abort.test.js +259 -0
- package/build/tools/replay-abort.test.js.map +1 -0
- package/build/tools/replay-add-conditional.test.d.ts +2 -0
- package/build/tools/replay-add-conditional.test.d.ts.map +1 -0
- package/build/tools/replay-add-conditional.test.js +205 -0
- package/build/tools/replay-add-conditional.test.js.map +1 -0
- package/build/tools/replay-background-run.test.d.ts +2 -0
- package/build/tools/replay-background-run.test.d.ts.map +1 -0
- package/build/tools/replay-background-run.test.js +176 -0
- package/build/tools/replay-background-run.test.js.map +1 -0
- package/build/tools/replay-capture-variables.test.d.ts +2 -0
- package/build/tools/replay-capture-variables.test.d.ts.map +1 -0
- package/build/tools/replay-capture-variables.test.js +331 -0
- package/build/tools/replay-capture-variables.test.js.map +1 -0
- package/build/tools/replay-conditional-idb-and-launch.test.d.ts +11 -0
- package/build/tools/replay-conditional-idb-and-launch.test.d.ts.map +1 -0
- package/build/tools/replay-conditional-idb-and-launch.test.js +429 -0
- package/build/tools/replay-conditional-idb-and-launch.test.js.map +1 -0
- package/build/tools/replay-conditional-timeout.test.d.ts +14 -0
- package/build/tools/replay-conditional-timeout.test.d.ts.map +1 -0
- package/build/tools/replay-conditional-timeout.test.js +126 -0
- package/build/tools/replay-conditional-timeout.test.js.map +1 -0
- package/build/tools/replay-declare.test.d.ts +2 -0
- package/build/tools/replay-declare.test.d.ts.map +1 -0
- package/build/tools/replay-declare.test.js +106 -0
- package/build/tools/replay-declare.test.js.map +1 -0
- package/build/tools/replay-declared-browser-cleanup.test.d.ts +2 -0
- package/build/tools/replay-declared-browser-cleanup.test.d.ts.map +1 -0
- package/build/tools/replay-declared-browser-cleanup.test.js +103 -0
- package/build/tools/replay-declared-browser-cleanup.test.js.map +1 -0
- package/build/tools/replay-declared-profile.test.d.ts +2 -0
- package/build/tools/replay-declared-profile.test.d.ts.map +1 -0
- package/build/tools/replay-declared-profile.test.js +116 -0
- package/build/tools/replay-declared-profile.test.js.map +1 -0
- package/build/tools/replay-executor.d.ts +556 -0
- package/build/tools/replay-executor.d.ts.map +1 -0
- package/build/tools/replay-executor.js +2347 -0
- package/build/tools/replay-executor.js.map +1 -0
- package/build/tools/replay-folder-save.test.d.ts +2 -0
- package/build/tools/replay-folder-save.test.d.ts.map +1 -0
- package/build/tools/replay-folder-save.test.js +63 -0
- package/build/tools/replay-folder-save.test.js.map +1 -0
- package/build/tools/replay-formatters.d.ts +148 -0
- package/build/tools/replay-formatters.d.ts.map +1 -0
- package/build/tools/replay-formatters.js +856 -0
- package/build/tools/replay-formatters.js.map +1 -0
- package/build/tools/replay-kill-chrome-on-finish.test.d.ts +2 -0
- package/build/tools/replay-kill-chrome-on-finish.test.d.ts.map +1 -0
- package/build/tools/replay-kill-chrome-on-finish.test.js +175 -0
- package/build/tools/replay-kill-chrome-on-finish.test.js.map +1 -0
- package/build/tools/replay-multi-connection.test.d.ts +2 -0
- package/build/tools/replay-multi-connection.test.d.ts.map +1 -0
- package/build/tools/replay-multi-connection.test.js +547 -0
- package/build/tools/replay-multi-connection.test.js.map +1 -0
- package/build/tools/replay-output-and-record-options.test.d.ts +2 -0
- package/build/tools/replay-output-and-record-options.test.d.ts.map +1 -0
- package/build/tools/replay-output-and-record-options.test.js +240 -0
- package/build/tools/replay-output-and-record-options.test.js.map +1 -0
- package/build/tools/replay-production-error-shape.test.d.ts +7 -0
- package/build/tools/replay-production-error-shape.test.d.ts.map +1 -0
- package/build/tools/replay-production-error-shape.test.js +93 -0
- package/build/tools/replay-production-error-shape.test.js.map +1 -0
- package/build/tools/replay-rebase.test.d.ts +2 -0
- package/build/tools/replay-rebase.test.d.ts.map +1 -0
- package/build/tools/replay-rebase.test.js +58 -0
- package/build/tools/replay-rebase.test.js.map +1 -0
- package/build/tools/replay-retry-classification.test.d.ts +9 -0
- package/build/tools/replay-retry-classification.test.d.ts.map +1 -0
- package/build/tools/replay-retry-classification.test.js +57 -0
- package/build/tools/replay-retry-classification.test.js.map +1 -0
- package/build/tools/replay-run-registry.d.ts +55 -0
- package/build/tools/replay-run-registry.d.ts.map +1 -0
- package/build/tools/replay-run-registry.js +65 -0
- package/build/tools/replay-run-registry.js.map +1 -0
- package/build/tools/replay-sequence-reload.test.d.ts +2 -0
- package/build/tools/replay-sequence-reload.test.d.ts.map +1 -0
- package/build/tools/replay-sequence-reload.test.js +82 -0
- package/build/tools/replay-sequence-reload.test.js.map +1 -0
- package/build/tools/replay-socket-scope.test.d.ts +2 -0
- package/build/tools/replay-socket-scope.test.d.ts.map +1 -0
- package/build/tools/replay-socket-scope.test.js +75 -0
- package/build/tools/replay-socket-scope.test.js.map +1 -0
- package/build/tools/replay-step-connection.test.d.ts +2 -0
- package/build/tools/replay-step-connection.test.d.ts.map +1 -0
- package/build/tools/replay-step-connection.test.js +292 -0
- package/build/tools/replay-step-connection.test.js.map +1 -0
- package/build/tools/replay-step-timeout.test.d.ts +2 -0
- package/build/tools/replay-step-timeout.test.d.ts.map +1 -0
- package/build/tools/replay-step-timeout.test.js +204 -0
- package/build/tools/replay-step-timeout.test.js.map +1 -0
- package/build/tools/replay-tags.test.d.ts +2 -0
- package/build/tools/replay-tags.test.d.ts.map +1 -0
- package/build/tools/replay-tags.test.js +99 -0
- package/build/tools/replay-tags.test.js.map +1 -0
- package/build/tools/replay-teardown-and-foreach.test.d.ts +13 -0
- package/build/tools/replay-teardown-and-foreach.test.d.ts.map +1 -0
- package/build/tools/replay-teardown-and-foreach.test.js +318 -0
- package/build/tools/replay-teardown-and-foreach.test.js.map +1 -0
- package/build/tools/replay-tool-name-validation.test.d.ts +2 -0
- package/build/tools/replay-tool-name-validation.test.d.ts.map +1 -0
- package/build/tools/replay-tool-name-validation.test.js +280 -0
- package/build/tools/replay-tool-name-validation.test.js.map +1 -0
- package/build/tools/replay-tools.d.ts +288 -0
- package/build/tools/replay-tools.d.ts.map +1 -0
- package/build/tools/replay-tools.js +2994 -0
- package/build/tools/replay-tools.js.map +1 -0
- package/build/tools/request-abort.test.d.ts +2 -0
- package/build/tools/request-abort.test.d.ts.map +1 -0
- package/build/tools/request-abort.test.js +130 -0
- package/build/tools/request-abort.test.js.map +1 -0
- package/build/tools/request-tools.d.ts +56 -0
- package/build/tools/request-tools.d.ts.map +1 -0
- package/build/tools/request-tools.js +174 -0
- package/build/tools/request-tools.js.map +1 -0
- package/build/tools/screenshot-tools.d.ts +135 -0
- package/build/tools/screenshot-tools.d.ts.map +1 -0
- package/build/tools/screenshot-tools.js +636 -0
- package/build/tools/screenshot-tools.js.map +1 -0
- package/build/tools/server-tools.d.ts +88 -0
- package/build/tools/server-tools.d.ts.map +1 -0
- package/build/tools/server-tools.js +485 -0
- package/build/tools/server-tools.js.map +1 -0
- package/build/tools/source-tools.d.ts +46 -0
- package/build/tools/source-tools.d.ts.map +1 -0
- package/build/tools/source-tools.js +47 -0
- package/build/tools/source-tools.js.map +1 -0
- package/build/tools/storage-tools.d.ts +141 -0
- package/build/tools/storage-tools.d.ts.map +1 -0
- package/build/tools/storage-tools.js +894 -0
- package/build/tools/storage-tools.js.map +1 -0
- package/build/tools/storage-tools.test.d.ts +13 -0
- package/build/tools/storage-tools.test.d.ts.map +1 -0
- package/build/tools/storage-tools.test.js +707 -0
- package/build/tools/storage-tools.test.js.map +1 -0
- package/build/tools/tab-tools.d.ts +42 -0
- package/build/tools/tab-tools.d.ts.map +1 -0
- package/build/tools/tab-tools.js +296 -0
- package/build/tools/tab-tools.js.map +1 -0
- package/build/tools/wait-tools.d.ts +85 -0
- package/build/tools/wait-tools.d.ts.map +1 -0
- package/build/tools/wait-tools.js +236 -0
- package/build/tools/wait-tools.js.map +1 -0
- package/build/tools/wait-tools.test.d.ts +9 -0
- package/build/tools/wait-tools.test.d.ts.map +1 -0
- package/build/tools/wait-tools.test.js +193 -0
- package/build/tools/wait-tools.test.js.map +1 -0
- package/build/types.d.ts +133 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +5 -0
- package/build/types.js.map +1 -0
- package/build/ui-verifier.d.ts +88 -0
- package/build/ui-verifier.d.ts.map +1 -0
- package/build/ui-verifier.js +540 -0
- package/build/ui-verifier.js.map +1 -0
- package/build/utils/abort.d.ts +68 -0
- package/build/utils/abort.d.ts.map +1 -0
- package/build/utils/abort.js +159 -0
- package/build/utils/abort.js.map +1 -0
- package/build/utils/abort.test.d.ts +2 -0
- package/build/utils/abort.test.d.ts.map +1 -0
- package/build/utils/abort.test.js +174 -0
- package/build/utils/abort.test.js.map +1 -0
- package/build/utils/modal-detection-core.d.ts +150 -0
- package/build/utils/modal-detection-core.d.ts.map +1 -0
- package/build/utils/modal-detection-core.js +332 -0
- package/build/utils/modal-detection-core.js.map +1 -0
- package/build/utils/modal-detection-core.test.d.ts +5 -0
- package/build/utils/modal-detection-core.test.d.ts.map +1 -0
- package/build/utils/modal-detection-core.test.js +492 -0
- package/build/utils/modal-detection-core.test.js.map +1 -0
- package/build/utils/modal-detector.d.ts +29 -0
- package/build/utils/modal-detector.d.ts.map +1 -0
- package/build/utils/modal-detector.js +281 -0
- package/build/utils/modal-detector.js.map +1 -0
- package/build/utils/modal-dismissal.d.ts +32 -0
- package/build/utils/modal-dismissal.d.ts.map +1 -0
- package/build/utils/modal-dismissal.js +190 -0
- package/build/utils/modal-dismissal.js.map +1 -0
- package/build/utils/port-check.d.ts +31 -0
- package/build/utils/port-check.d.ts.map +1 -0
- package/build/utils/port-check.js +87 -0
- package/build/utils/port-check.js.map +1 -0
- package/build/utils/port-check.test.d.ts +2 -0
- package/build/utils/port-check.test.d.ts.map +1 -0
- package/build/utils/port-check.test.js +66 -0
- package/build/utils/port-check.test.js.map +1 -0
- package/build/utils/selector-resolver.d.ts +66 -0
- package/build/utils/selector-resolver.d.ts.map +1 -0
- package/build/utils/selector-resolver.js +200 -0
- package/build/utils/selector-resolver.js.map +1 -0
- package/build/validation-helpers.d.ts +41 -0
- package/build/validation-helpers.d.ts.map +1 -0
- package/build/validation-helpers.js +236 -0
- package/build/validation-helpers.js.map +1 -0
- package/build/window-sizing.d.ts +26 -0
- package/build/window-sizing.d.ts.map +1 -0
- package/build/window-sizing.js +87 -0
- package/build/window-sizing.js.map +1 -0
- package/build/window-sizing.test.d.ts +8 -0
- package/build/window-sizing.test.d.ts.map +1 -0
- package/build/window-sizing.test.js +113 -0
- package/build/window-sizing.test.js.map +1 -0
- package/docs/README.md +74 -0
- package/docs/automation.md +562 -0
- package/docs/debugging.md +229 -0
- package/docs/installation.md +133 -0
- package/docs/instructions.md +227 -0
- package/docs/mcp-instructions.md +15 -0
- package/docs/message-system.md +327 -0
- package/docs/messages.md +3480 -0
- package/docs/parser-plugins.md +132 -0
- package/docs/replay.md +1411 -0
- package/docs/troubleshooting.md +272 -0
- package/docs/working_with_llm_notes.md +5 -0
- package/package.json +87 -0
- package/skills/devharness/SKILL.md +195 -0
- package/skills/devharness/references/sequences.md +613 -0
- package/skills/devharness/references/tool-categories.md +99 -0
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replay Formatters - Response formatting for replay tool actions
|
|
3
|
+
*/
|
|
4
|
+
import { isMouseEvent, isKeyboardEvent, isNavigationEvent, isCommentEvent, isPasteEvent, } from '../interaction-recorder.js';
|
|
5
|
+
import { getFormattedResponse } from '../messages.js';
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// Result Formatting
|
|
8
|
+
// =============================================================================
|
|
9
|
+
/**
|
|
10
|
+
* Format execution results for display
|
|
11
|
+
*/
|
|
12
|
+
export function formatExecutionResults(sequenceName, results, totalCommands, durationMs,
|
|
13
|
+
/**
|
|
14
|
+
* Reported in its own section, never folded into the counts above. Teardown
|
|
15
|
+
* is cleanup, so a failure in it must not turn a passing run red - or make a
|
|
16
|
+
* failing one look like it failed somewhere it didn't.
|
|
17
|
+
*/
|
|
18
|
+
teardown) {
|
|
19
|
+
const successful = results.filter(r => r.success).length;
|
|
20
|
+
const failed = results.filter(r => !r.success).length;
|
|
21
|
+
let response;
|
|
22
|
+
if (failed > 0) {
|
|
23
|
+
const failedResult = results.find(r => !r.success);
|
|
24
|
+
response = getFormattedResponse('REPLAY_RUN_FAILED', {
|
|
25
|
+
sequenceName,
|
|
26
|
+
failedStep: failedResult.step,
|
|
27
|
+
failedTool: failedResult.tool
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
response = getFormattedResponse('REPLAY_RUN_SUCCESS', {
|
|
32
|
+
sequenceName,
|
|
33
|
+
successful,
|
|
34
|
+
total: totalCommands,
|
|
35
|
+
duration: (durationMs / 1000).toFixed(1)
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
// Stats section
|
|
39
|
+
response += `\n\n**Executed:** ${results.length} of ${totalCommands} commands`;
|
|
40
|
+
response += `\n**Successful:** ${successful}`;
|
|
41
|
+
response += `\n**Failed:** ${failed}`;
|
|
42
|
+
response += `\n**Duration:** ${(durationMs / 1000).toFixed(1)}s`;
|
|
43
|
+
if (failed > 0) {
|
|
44
|
+
response += `\n\n**Failed Commands**\n`;
|
|
45
|
+
results.filter(r => !r.success).forEach((r) => {
|
|
46
|
+
if ((r.tool === 'conditional' || r.tool === 'forEach') && r.substeps) {
|
|
47
|
+
const scope = r.tool === 'forEach'
|
|
48
|
+
? `${r.sequenceName}, item ${r.iterations} of ${r.itemsFound}`
|
|
49
|
+
: r.sequenceName;
|
|
50
|
+
response += `${r.step}. **${r.tool}** (${scope})\n`;
|
|
51
|
+
response += ` **Error:** ${r.error}\n`;
|
|
52
|
+
// Show substeps - but skip redundant error messages
|
|
53
|
+
r.substeps.forEach((sub) => {
|
|
54
|
+
const icon = sub.success ? '✓' : '✗';
|
|
55
|
+
response += ` ${r.step}.${sub.step}. ${sub.tool} ${icon}`;
|
|
56
|
+
// Only show substep error if it's different from the parent error
|
|
57
|
+
if (!sub.success && sub.error && sub.error !== r.error) {
|
|
58
|
+
response += ` - ${sub.error}`;
|
|
59
|
+
}
|
|
60
|
+
response += `\n`;
|
|
61
|
+
});
|
|
62
|
+
response += `\n`;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
response += `${r.step}. **${r.tool}**\n`;
|
|
66
|
+
response += ` **Error:** ${r.error}\n\n`;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (successful > 0) {
|
|
71
|
+
response += `\n\n**Successful Commands**\n`;
|
|
72
|
+
results.filter(r => r.success).forEach((r) => {
|
|
73
|
+
if (r.tool === 'conditional') {
|
|
74
|
+
// Format conditional with substeps
|
|
75
|
+
if (r.conditionMet && r.substeps && r.substeps.length > 0) {
|
|
76
|
+
response += `${r.step}. **${r.tool}** (${r.sequenceName}) ✓ - ran ${r.substeps.length} substeps\n`;
|
|
77
|
+
r.substeps.forEach((sub) => {
|
|
78
|
+
const icon = sub.success ? '✓' : '✗';
|
|
79
|
+
response += ` ${r.step}.${sub.step}. ${sub.tool} ${icon}\n`;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
else if (r.conditionMet) {
|
|
83
|
+
// The condition HELD and the sequence still ran nothing - every step
|
|
84
|
+
// was already satisfied (a launchChrome for a browser that exists).
|
|
85
|
+
// Reporting this as "condition not met" would describe the opposite
|
|
86
|
+
// of what happened.
|
|
87
|
+
response += `${r.step}. **${r.tool}** (${r.sequenceName}) ✓ - condition met, no steps left to run\n`;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// Skipped because condition not met (not an error, just false)
|
|
91
|
+
response += `${r.step}. **${r.tool}** (${r.sequenceName}) ○ - skipped (condition not met)\n`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (r.tool === 'forEach') {
|
|
95
|
+
// An empty source is a legitimate outcome, not a silent nothing: a
|
|
96
|
+
// converge loop with nothing left to clean up looks identical to a
|
|
97
|
+
// broken selector unless the count is stated.
|
|
98
|
+
if (r.iterations && r.substeps && r.substeps.length > 0) {
|
|
99
|
+
response += `${r.step}. **${r.tool}** (${r.sequenceName}) ✓ - ran ${r.iterations} of ${r.itemsFound} item(s)\n`;
|
|
100
|
+
r.substeps.forEach((sub) => {
|
|
101
|
+
const icon = sub.success ? '✓' : '✗';
|
|
102
|
+
response += ` ${r.step}.${sub.step}. ${sub.tool} ${icon}\n`;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
response += `${r.step}. **${r.tool}** (${r.sequenceName}) ○ - ${r.itemsFound || 0} item(s) found, none ran\n`;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
response += `${r.step}. **${r.tool}** ✓\n`;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (teardown && teardown.results.length > 0) {
|
|
115
|
+
const tdFailed = teardown.results.filter(r => !r.success).length;
|
|
116
|
+
response += `\n\n**Teardown** (${teardown.results.length} step(s)`;
|
|
117
|
+
response += tdFailed > 0 ? `, ${tdFailed} failed - does not change the run's verdict)\n` : `)\n`;
|
|
118
|
+
teardown.results.forEach((r) => {
|
|
119
|
+
const icon = r.success ? '✓' : '✗';
|
|
120
|
+
response += `T${r.step}. ${r.tool} ${icon}`;
|
|
121
|
+
if (!r.success && r.error)
|
|
122
|
+
response += ` - ${r.error}`;
|
|
123
|
+
response += `\n`;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
return response;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Format paused sequence response
|
|
130
|
+
*/
|
|
131
|
+
export function formatPausedResponse(sequence, results, pausedAtStep, durationMs) {
|
|
132
|
+
const commands = sequence.commands;
|
|
133
|
+
const successful = results.filter(r => r.success).length;
|
|
134
|
+
const remaining = commands.length - pausedAtStep;
|
|
135
|
+
let response = getFormattedResponse('REPLAY_PAUSED', {
|
|
136
|
+
sequenceName: sequence.name,
|
|
137
|
+
pausedStep: pausedAtStep,
|
|
138
|
+
total: commands.length,
|
|
139
|
+
remaining
|
|
140
|
+
});
|
|
141
|
+
response += `\n\n**Executed:** ${successful} commands in ${(durationMs / 1000).toFixed(1)}s`;
|
|
142
|
+
response += `\n\n**Completed Steps**\n`;
|
|
143
|
+
results.forEach((r) => {
|
|
144
|
+
response += `${r.step}. **${r.tool}** ✓\n`;
|
|
145
|
+
});
|
|
146
|
+
response += `\n**Next Steps**\n`;
|
|
147
|
+
for (let j = pausedAtStep; j < Math.min(pausedAtStep + 3, commands.length); j++) {
|
|
148
|
+
response += `${j + 1}. **${commands[j].tool}**\n`;
|
|
149
|
+
}
|
|
150
|
+
if (commands.length > pausedAtStep + 3) {
|
|
151
|
+
response += `... and ${commands.length - pausedAtStep - 3} more\n`;
|
|
152
|
+
}
|
|
153
|
+
response += `\n---\n\n**Actions**\n`;
|
|
154
|
+
response += `- Continue: \`replay({ action: 'step' })\` or \`replay({ action: 'step', stepCount: N })\`\n`;
|
|
155
|
+
response += `- Finish all: \`replay({ action: 'finish' })\`\n`;
|
|
156
|
+
response += `- Check status: \`replay({ action: 'status' })\`\n`;
|
|
157
|
+
response += `- Insert commands: \`replay({ action: 'insert' })\`\n`;
|
|
158
|
+
return response;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Format click validation failure response (paused for inspection/retry)
|
|
162
|
+
*/
|
|
163
|
+
export function formatClickValidationFailure(sequence, results, pausedAtStep, durationMs, failure, connectionReason) {
|
|
164
|
+
const commands = sequence.commands;
|
|
165
|
+
const successful = results.filter(r => r.success).length;
|
|
166
|
+
const remaining = commands.length - pausedAtStep;
|
|
167
|
+
let response = `**Click Validation Failed**\n`;
|
|
168
|
+
response += `${sequence.name}: Paused at step ${pausedAtStep} of ${commands.length}, ${remaining} remaining\n\n`;
|
|
169
|
+
response += `**Executed:** ${successful} commands in ${(durationMs / 1000).toFixed(1)}s\n\n`;
|
|
170
|
+
response += `**Validation Error at Step ${failure.step}**\n`;
|
|
171
|
+
response += `- Selector: \`${failure.selector}\`\n`;
|
|
172
|
+
for (const err of failure.errors) {
|
|
173
|
+
response += `- ❌ ${err}\n`;
|
|
174
|
+
}
|
|
175
|
+
for (const warn of failure.warnings) {
|
|
176
|
+
response += `- ⚠️ ${warn}\n`;
|
|
177
|
+
}
|
|
178
|
+
if (failure.info?.length > 0) {
|
|
179
|
+
for (const infoMsg of failure.info) {
|
|
180
|
+
response += `- ℹ️ ${infoMsg}\n`;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
response += `\n**Completed Steps**\n`;
|
|
184
|
+
results.filter(r => r.success).forEach((r) => {
|
|
185
|
+
response += `${r.step}. **${r.tool}** ✓\n`;
|
|
186
|
+
});
|
|
187
|
+
response += `\n---\n\n**Actions**\n`;
|
|
188
|
+
response += `- Inspect error: \`console({ action: 'list', type: 'error', connectionReason: '${connectionReason}' })\`\n`;
|
|
189
|
+
response += `- Retry step: \`replay({ action: 'step' })\`\n`;
|
|
190
|
+
response += `- Skip and continue: \`replay({ action: 'step', stepCount: 2 })\`\n`;
|
|
191
|
+
response += `- Finish remaining: \`replay({ action: 'finish' })\`\n`;
|
|
192
|
+
response += `- Cancel: \`replay({ action: 'cancel' })\`\n`;
|
|
193
|
+
return response;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Format breakpoint hit response
|
|
197
|
+
*/
|
|
198
|
+
export function formatBreakpointHit(sequenceName, results, totalCommands, durationMs, breakpointInfo, connectionReason) {
|
|
199
|
+
const location = `${breakpointInfo.url}:${breakpointInfo.lineNumber}`;
|
|
200
|
+
let response = getFormattedResponse('REPLAY_BREAKPOINT_HIT', {
|
|
201
|
+
sequenceName,
|
|
202
|
+
location,
|
|
203
|
+
step: results.length,
|
|
204
|
+
total: totalCommands
|
|
205
|
+
});
|
|
206
|
+
response += `\n\n**Location:** \`${breakpointInfo.url}:${breakpointInfo.lineNumber}\``;
|
|
207
|
+
if (breakpointInfo.functionName) {
|
|
208
|
+
response += `\n**Function:** \`${breakpointInfo.functionName}\``;
|
|
209
|
+
}
|
|
210
|
+
response += `\n**Step:** ${results.length} of ${totalCommands}`;
|
|
211
|
+
response += `\n**Duration:** ${(durationMs / 1000).toFixed(1)}s`;
|
|
212
|
+
response += `\n\n**Completed Steps**\n`;
|
|
213
|
+
results.forEach((r) => {
|
|
214
|
+
response += `${r.step}. **${r.tool}** ✓\n`;
|
|
215
|
+
});
|
|
216
|
+
response += `\n---\n\n**Debug Actions**\n`;
|
|
217
|
+
response += `- Inspect call stack: \`inspect({ action: 'getCallStack', connectionReason: '${connectionReason}' })\`\n`;
|
|
218
|
+
response += `- Get variables: \`inspect({ action: 'getVariables', connectionReason: '${connectionReason}', callFrameId: '<from call stack>' })\`\n`;
|
|
219
|
+
response += `- Resume execution: \`execution({ action: 'resume', connectionReason: '${connectionReason}' })\`\n`;
|
|
220
|
+
response += `- Step over: \`execution({ action: 'stepOver', connectionReason: '${connectionReason}' })\`\n`;
|
|
221
|
+
return response;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Format debug state section
|
|
225
|
+
*/
|
|
226
|
+
export function formatDebugState(debugState, connectionReason) {
|
|
227
|
+
if (!debugState.isPaused && debugState.breakpointCount === 0) {
|
|
228
|
+
return '';
|
|
229
|
+
}
|
|
230
|
+
let section = `\n\n**Debug State**\n`;
|
|
231
|
+
if (debugState.isPaused) {
|
|
232
|
+
section += `\n**Execution paused** at ${debugState.pauseLocation}\n\n`;
|
|
233
|
+
section += `**Next steps:**\n`;
|
|
234
|
+
section += `- Inspect call stack: \`inspect({ action: 'getCallStack', connectionReason: '${connectionReason}' })\`\n`;
|
|
235
|
+
section += `- Get variables: \`inspect({ action: 'getVariables', connectionReason: '${connectionReason}', callFrameId: '<from call stack>' })\`\n`;
|
|
236
|
+
section += `- Resume execution: \`execution({ action: 'resume', connectionReason: '${connectionReason}' })\`\n`;
|
|
237
|
+
section += `- Step over: \`execution({ action: 'stepOver', connectionReason: '${connectionReason}' })\`\n`;
|
|
238
|
+
}
|
|
239
|
+
if (debugState.breakpointCount > 0) {
|
|
240
|
+
section += `\n**${debugState.breakpointCount} active breakpoint${debugState.breakpointCount > 1 ? 's' : ''}**\n`;
|
|
241
|
+
section += `- List breakpoints: \`breakpoint({ action: 'list', connectionReason: '${connectionReason}' })\`\n`;
|
|
242
|
+
section += `- Remove all: \`breakpoint({ action: 'remove', connectionReason: '${connectionReason}', breakpointId: '<id>' })\`\n`;
|
|
243
|
+
}
|
|
244
|
+
return section;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Extract customizable text variables from sequence commands
|
|
248
|
+
*/
|
|
249
|
+
export function extractTextVariables(commands) {
|
|
250
|
+
const variables = {};
|
|
251
|
+
commands.forEach((cmd, cmdIdx) => {
|
|
252
|
+
if (cmd.tool === 'input' && cmd.params.action === 'type' && cmd.params.text) {
|
|
253
|
+
const varName = `var_${cmdIdx}_${cmd.params.selector?.replace(/[^a-zA-Z0-9]/g, '_') || 'text'}`;
|
|
254
|
+
if (!variables[varName]) {
|
|
255
|
+
variables[varName] = { value: cmd.params.text, locations: [] };
|
|
256
|
+
}
|
|
257
|
+
variables[varName].locations.push(`Command ${cmdIdx + 1}: ${cmd.tool} -> ${cmd.params.selector}`);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
return variables;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Format variable prompt for user to customize values before execution
|
|
264
|
+
*/
|
|
265
|
+
export function formatVariablePrompt(sequenceName, sequenceIdOrName, variables, connectionReason) {
|
|
266
|
+
let response = getFormattedResponse('REPLAY_VARIABLE_PROMPT', {
|
|
267
|
+
sequenceName,
|
|
268
|
+
variableCount: Object.keys(variables).length
|
|
269
|
+
});
|
|
270
|
+
response += `\n\n**Customizable text parameter(s):**\n`;
|
|
271
|
+
Object.entries(variables).forEach(([varName, data]) => {
|
|
272
|
+
response += `- \`${varName}\`: "${data.value}"\n`;
|
|
273
|
+
});
|
|
274
|
+
response += `\n**Execute:**\n\n`;
|
|
275
|
+
response += `**Option 1: Keep original values**\n`;
|
|
276
|
+
response += `\`\`\`javascript\n`;
|
|
277
|
+
response += `replay({ action: 'run', name: '${sequenceIdOrName}'`;
|
|
278
|
+
if (connectionReason) {
|
|
279
|
+
response += `, connectionReason: '${connectionReason}'`;
|
|
280
|
+
}
|
|
281
|
+
response += `, variables: {} })\n`;
|
|
282
|
+
response += `\`\`\`\n\n`;
|
|
283
|
+
response += `**Option 2: Custom values** (replace variable values as needed)\n`;
|
|
284
|
+
response += `\`\`\`javascript\n`;
|
|
285
|
+
response += `replay({ action: 'run', name: '${sequenceIdOrName}'`;
|
|
286
|
+
if (connectionReason) {
|
|
287
|
+
response += `, connectionReason: '${connectionReason}'`;
|
|
288
|
+
}
|
|
289
|
+
response += `, variables: {\n`;
|
|
290
|
+
Object.keys(variables).forEach((varName, idx, arr) => {
|
|
291
|
+
response += ` "${varName}": "custom-value"${idx < arr.length - 1 ? ',' : ''}\n`;
|
|
292
|
+
});
|
|
293
|
+
response += `} })\n`;
|
|
294
|
+
response += `\`\`\``;
|
|
295
|
+
return response;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Format command history listing
|
|
299
|
+
*/
|
|
300
|
+
export function formatHistory(history, totalCount) {
|
|
301
|
+
if (history.length === 0) {
|
|
302
|
+
return getFormattedResponse('REPLAY_HISTORY_EMPTY', {});
|
|
303
|
+
}
|
|
304
|
+
// Use message template for first two lines
|
|
305
|
+
let response = getFormattedResponse('REPLAY_HISTORY', {
|
|
306
|
+
count: history.length,
|
|
307
|
+
totalCount: totalCount
|
|
308
|
+
});
|
|
309
|
+
history.forEach((cmd) => {
|
|
310
|
+
const paramStr = JSON.stringify(cmd.params);
|
|
311
|
+
const truncatedParams = paramStr.length > 60 ? paramStr.slice(0, 60) + '...' : paramStr;
|
|
312
|
+
let line = `\n${cmd.index}. **${cmd.tool}** - ${truncatedParams}`;
|
|
313
|
+
// Show delay and comment if present
|
|
314
|
+
const extras = [];
|
|
315
|
+
if (cmd.delay)
|
|
316
|
+
extras.push(`delay:${cmd.delay}ms`);
|
|
317
|
+
if (cmd.comment)
|
|
318
|
+
extras.push(`"${cmd.comment.length > 30 ? cmd.comment.slice(0, 30) + '...' : cmd.comment}"`);
|
|
319
|
+
if (extras.length > 0)
|
|
320
|
+
line += ` *(${extras.join(', ')})*`;
|
|
321
|
+
response += line;
|
|
322
|
+
});
|
|
323
|
+
response += `\n\n---\n\nCreate sequence: \`replay({ action: 'create', name: '...', indices: [${history.slice(0, 3).map(c => c.index).join(', ')}] })\``;
|
|
324
|
+
return response;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Format sequence created response
|
|
328
|
+
*/
|
|
329
|
+
export function formatSequenceCreated(sequence) {
|
|
330
|
+
let response = getFormattedResponse('REPLAY_SEQUENCE_CREATED', {
|
|
331
|
+
name: sequence.name,
|
|
332
|
+
id: sequence.id,
|
|
333
|
+
commandCount: sequence.commands.length
|
|
334
|
+
});
|
|
335
|
+
// Optional metadata
|
|
336
|
+
let hasMetadata = false;
|
|
337
|
+
if (sequence.description) {
|
|
338
|
+
response += `${hasMetadata ? '\n' : '\n\n'}**Description:** ${sequence.description}`;
|
|
339
|
+
hasMetadata = true;
|
|
340
|
+
}
|
|
341
|
+
if (sequence.expectedOutcome) {
|
|
342
|
+
response += `${hasMetadata ? '\n' : '\n\n'}**Expected Outcome:** ${sequence.expectedOutcome}`;
|
|
343
|
+
hasMetadata = true;
|
|
344
|
+
}
|
|
345
|
+
if (sequence.startUrl) {
|
|
346
|
+
response += `${hasMetadata ? '\n' : '\n\n'}**Start URL:** ${sequence.startUrl}`;
|
|
347
|
+
hasMetadata = true;
|
|
348
|
+
}
|
|
349
|
+
response += `\n\n**Commands in Sequence**\n`;
|
|
350
|
+
sequence.commands.forEach((cmd, idx) => {
|
|
351
|
+
response += `${idx + 1}. **${cmd.tool}**\n`;
|
|
352
|
+
response += `\`\`\`json\n${JSON.stringify(cmd.params, null, 2)}\n\`\`\`\n\n`;
|
|
353
|
+
});
|
|
354
|
+
response += `---\n\n`;
|
|
355
|
+
response += `**Run this sequence:**\n`;
|
|
356
|
+
response += `\`replay({ action: 'run', sequenceId: '${sequence.id}' })\``;
|
|
357
|
+
return response;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Format sequence list
|
|
361
|
+
*/
|
|
362
|
+
export function formatSequenceList(sequences) {
|
|
363
|
+
if (sequences.length === 0) {
|
|
364
|
+
let response = getFormattedResponse('REPLAY_SEQUENCE_LIST_EMPTY', {});
|
|
365
|
+
response += `\n\n**Create a sequence:**\n`;
|
|
366
|
+
response += `1. View command history: \`replay({ action: 'history' })\`\n`;
|
|
367
|
+
response += `2. Create sequence: \`replay({ action: 'create', name: 'my-workflow', indices: [1, 2, 3] })\``;
|
|
368
|
+
return response;
|
|
369
|
+
}
|
|
370
|
+
let response = getFormattedResponse('REPLAY_SEQUENCE_LIST', {
|
|
371
|
+
count: sequences.length
|
|
372
|
+
});
|
|
373
|
+
sequences.forEach((seq, idx) => {
|
|
374
|
+
const age = Math.floor((Date.now() - seq.createdAt) / 1000 / 60);
|
|
375
|
+
response += `\n\n**${idx + 1}. ${seq.name}**\n`;
|
|
376
|
+
response += `- **ID:** \`${seq.id}\`\n`;
|
|
377
|
+
if (seq.description) {
|
|
378
|
+
response += `- **Description:** ${seq.description}\n`;
|
|
379
|
+
}
|
|
380
|
+
if (seq.expectedOutcome) {
|
|
381
|
+
response += `- **Expected Outcome:** ${seq.expectedOutcome}\n`;
|
|
382
|
+
}
|
|
383
|
+
if (seq.startUrl) {
|
|
384
|
+
response += `- **Start URL:** ${seq.startUrl}\n`;
|
|
385
|
+
}
|
|
386
|
+
response += `- **Commands:** ${seq.commands.length}\n`;
|
|
387
|
+
response += `- **Created:** ${age} minutes ago`;
|
|
388
|
+
});
|
|
389
|
+
response += `\n\n---\n\n`;
|
|
390
|
+
response += `**Actions:**\n`;
|
|
391
|
+
response += `- View details: \`replay({ action: 'get', sequenceId: 'seq-id' })\`\n`;
|
|
392
|
+
response += `- Execute: \`replay({ action: 'run', sequenceId: 'seq-id' })\`\n`;
|
|
393
|
+
response += `- Delete: \`replay({ action: 'delete', sequenceId: 'seq-id' })\``;
|
|
394
|
+
return response;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Format sequence details
|
|
398
|
+
*/
|
|
399
|
+
export function formatSequenceDetails(sequence) {
|
|
400
|
+
let response = getFormattedResponse('REPLAY_SEQUENCE_DETAILS', {
|
|
401
|
+
name: sequence.name,
|
|
402
|
+
commandCount: sequence.commands.length
|
|
403
|
+
});
|
|
404
|
+
response += `\n\n**ID:** \`${sequence.id}\``;
|
|
405
|
+
if (sequence.description) {
|
|
406
|
+
response += `\n**Description:** ${sequence.description}`;
|
|
407
|
+
}
|
|
408
|
+
if (sequence.expectedOutcome) {
|
|
409
|
+
response += `\n**Expected Outcome:** ${sequence.expectedOutcome}`;
|
|
410
|
+
}
|
|
411
|
+
if (sequence.startUrl) {
|
|
412
|
+
response += `\n**Start URL:** ${sequence.startUrl}`;
|
|
413
|
+
}
|
|
414
|
+
response += `\n**Created:** ${new Date(sequence.createdAt).toLocaleString()}`;
|
|
415
|
+
// Show variables if any exist
|
|
416
|
+
const variables = extractTextVariables(sequence.commands);
|
|
417
|
+
if (Object.keys(variables).length > 0) {
|
|
418
|
+
response += `\n\n**Variables (${Object.keys(variables).length}):**\n`;
|
|
419
|
+
Object.entries(variables).forEach(([varName, data]) => {
|
|
420
|
+
response += `- \`${varName}\`: "${data.value}"\n`;
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
response += `\n\n**Commands**\n`;
|
|
424
|
+
sequence.commands.forEach((cmd, idx) => {
|
|
425
|
+
response += `### ${idx + 1}. ${cmd.tool}\n`;
|
|
426
|
+
response += `**Parameters:**\n\`\`\`json\n${JSON.stringify(cmd.params, null, 2)}\n\`\`\`\n\n`;
|
|
427
|
+
});
|
|
428
|
+
response += `---\n\n`;
|
|
429
|
+
response += `**Run:** \`replay({ action: 'run', name: '${sequence.name}' })\``;
|
|
430
|
+
return response;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Format saved sequences on disk listing
|
|
434
|
+
* Categories:
|
|
435
|
+
* - Saved: Regular sequences in .cdp-tools/sequences/
|
|
436
|
+
* - Issues: Issue sequences that are in_progress (or all if showAll)
|
|
437
|
+
* - Abandoned: Issue sequences without a linked issue (orphaned)
|
|
438
|
+
*/
|
|
439
|
+
export function formatSavedSequencesList(sequences, issueSequences, showAll = false) {
|
|
440
|
+
// Categorize issue sequences
|
|
441
|
+
const activeIssues = [];
|
|
442
|
+
const completedIssues = [];
|
|
443
|
+
const abandoned = [];
|
|
444
|
+
if (issueSequences) {
|
|
445
|
+
for (const seq of issueSequences) {
|
|
446
|
+
if (!seq.issueId) {
|
|
447
|
+
// No linked issue - abandoned/orphaned
|
|
448
|
+
abandoned.push(seq);
|
|
449
|
+
}
|
|
450
|
+
else if (seq.issueStatus === 'in_progress') {
|
|
451
|
+
// Only in_progress issues are shown by default
|
|
452
|
+
activeIssues.push(seq);
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
// Everything else (pending, acknowledged, fixed, implemented) goes to completed
|
|
456
|
+
completedIssues.push(seq);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
const hasSequences = sequences.length > 0;
|
|
461
|
+
const hasActiveIssues = activeIssues.length > 0;
|
|
462
|
+
const hasCompletedIssues = completedIssues.length > 0;
|
|
463
|
+
const hasAbandoned = abandoned.length > 0;
|
|
464
|
+
const hasAnythingToShow = hasSequences || hasActiveIssues || (showAll && (hasCompletedIssues || hasAbandoned));
|
|
465
|
+
if (!hasAnythingToShow) {
|
|
466
|
+
return getFormattedResponse('REPLAY_SAVED_EMPTY', {});
|
|
467
|
+
}
|
|
468
|
+
let response = '';
|
|
469
|
+
// Format regular sequences (Saved)
|
|
470
|
+
if (hasSequences) {
|
|
471
|
+
const sorted = [...sequences].sort((a, b) => {
|
|
472
|
+
const tsA = parseInt((a.id || '').replace('seq-', ''), 10) || 0;
|
|
473
|
+
const tsB = parseInt((b.id || '').replace('seq-', ''), 10) || 0;
|
|
474
|
+
return tsA - tsB;
|
|
475
|
+
});
|
|
476
|
+
response = `**Saved** (${sorted.length})\n`;
|
|
477
|
+
sorted.forEach((seq, idx) => {
|
|
478
|
+
const locationTag = seq.location === 'global' ? ' [global]' : '';
|
|
479
|
+
response += `${idx + 1}. ${seq.name} (${seq.commandCount})${locationTag}\n`;
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
// Format active issue sequences (Issues)
|
|
483
|
+
if (hasActiveIssues) {
|
|
484
|
+
const sortedIssues = [...activeIssues].sort((a, b) => (a.issueId || 0) - (b.issueId || 0));
|
|
485
|
+
if (response)
|
|
486
|
+
response += '\n';
|
|
487
|
+
response += `**Issues** (${sortedIssues.length})\n`;
|
|
488
|
+
sortedIssues.forEach((seq, idx) => {
|
|
489
|
+
const tag = `[${seq.issueType} #${seq.issueId} - ${seq.issueStatus}]`;
|
|
490
|
+
response += `${idx + 1}. ${tag} ${seq.name} (${seq.commandCount})\n`;
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
// Format completed issues (only if showAll)
|
|
494
|
+
if (showAll && hasCompletedIssues) {
|
|
495
|
+
const sortedCompleted = [...completedIssues].sort((a, b) => (a.issueId || 0) - (b.issueId || 0));
|
|
496
|
+
if (response)
|
|
497
|
+
response += '\n';
|
|
498
|
+
response += `**Completed** (${sortedCompleted.length})\n`;
|
|
499
|
+
sortedCompleted.forEach((seq, idx) => {
|
|
500
|
+
const tag = `[${seq.issueType} #${seq.issueId} - ${seq.issueStatus}]`;
|
|
501
|
+
response += `${idx + 1}. ${tag} ${seq.name} (${seq.commandCount})\n`;
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
// Format abandoned sequences (only if showAll)
|
|
505
|
+
if (showAll && hasAbandoned) {
|
|
506
|
+
const sortedAbandoned = [...abandoned].sort((a, b) => {
|
|
507
|
+
const tsA = parseInt((a.id || '').replace('seq-', ''), 10) || 0;
|
|
508
|
+
const tsB = parseInt((b.id || '').replace('seq-', ''), 10) || 0;
|
|
509
|
+
return tsA - tsB;
|
|
510
|
+
});
|
|
511
|
+
if (response)
|
|
512
|
+
response += '\n';
|
|
513
|
+
response += `**Abandoned** (${sortedAbandoned.length})\n`;
|
|
514
|
+
sortedAbandoned.forEach((seq, idx) => {
|
|
515
|
+
response += `${idx + 1}. ${seq.name} (${seq.commandCount})\n`;
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
// Show hint about hidden items
|
|
519
|
+
if (!showAll && (hasCompletedIssues || hasAbandoned)) {
|
|
520
|
+
const hiddenCount = completedIssues.length + abandoned.length;
|
|
521
|
+
response += `\n_${hiddenCount} other sequence(s) hidden. Use showAll: true to see all._\n`;
|
|
522
|
+
}
|
|
523
|
+
response += `\nRun: \`replay({ action: 'run', name: '<name>' })\``;
|
|
524
|
+
return response;
|
|
525
|
+
}
|
|
526
|
+
// =============================================================================
|
|
527
|
+
// Status & Step Formatting
|
|
528
|
+
// =============================================================================
|
|
529
|
+
/**
|
|
530
|
+
* Format active sequence status
|
|
531
|
+
*/
|
|
532
|
+
export function formatActiveStatus(activeSeq, commandsSincePause) {
|
|
533
|
+
const pausedDuration = Math.round((Date.now() - activeSeq.pausedAt) / 1000);
|
|
534
|
+
let response = getFormattedResponse('REPLAY_ACTIVE_STATUS', {
|
|
535
|
+
sequenceName: activeSeq.sequenceName,
|
|
536
|
+
currentStep: activeSeq.currentStep,
|
|
537
|
+
totalSteps: activeSeq.totalSteps
|
|
538
|
+
});
|
|
539
|
+
response += `\n\n**Connection:** ${activeSeq.connectionReason || 'none'}`;
|
|
540
|
+
response += `\n**Paused for:** ${pausedDuration}s`;
|
|
541
|
+
if (commandsSincePause.length > 0) {
|
|
542
|
+
response += `\n\n**Commands Since Pause (${commandsSincePause.length})**\n`;
|
|
543
|
+
commandsSincePause.forEach((cmd, idx) => {
|
|
544
|
+
response += `${idx + 1}. [#${cmd.index}] **${cmd.tool}**\n`;
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
response += `\n---\n\n**Actions**\n`;
|
|
548
|
+
response += `- Continue: \`replay({ action: 'step' })\`\n`;
|
|
549
|
+
response += `- Finish all: \`replay({ action: 'finish' })\`\n`;
|
|
550
|
+
if (commandsSincePause.length > 0) {
|
|
551
|
+
response += `- Insert commands: \`replay({ action: 'insert' })\`\n`;
|
|
552
|
+
}
|
|
553
|
+
return response;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Format step execution results
|
|
557
|
+
*/
|
|
558
|
+
export function formatStepResults(sequenceName, results, startStep, totalCommands, failed) {
|
|
559
|
+
let response;
|
|
560
|
+
if (failed) {
|
|
561
|
+
const failedResult = results.find(r => !r.success);
|
|
562
|
+
response = getFormattedResponse('REPLAY_STEP_FAILED', {
|
|
563
|
+
sequenceName,
|
|
564
|
+
failedStep: failedResult.step,
|
|
565
|
+
failedTool: failedResult.tool
|
|
566
|
+
});
|
|
567
|
+
response += `\n\n**Error:** ${failedResult.error}`;
|
|
568
|
+
response += `\n\nSequence cancelled due to error.`;
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
const lastExecuted = results.length > 0 ? results[results.length - 1].step : startStep;
|
|
572
|
+
const remaining = totalCommands - lastExecuted;
|
|
573
|
+
if (lastExecuted >= totalCommands) {
|
|
574
|
+
response = getFormattedResponse('REPLAY_STEP_COMPLETE', {
|
|
575
|
+
sequenceName,
|
|
576
|
+
total: totalCommands
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
response = getFormattedResponse('REPLAY_STEP_SUCCESS', {
|
|
581
|
+
sequenceName,
|
|
582
|
+
stepCount: results.length,
|
|
583
|
+
remaining
|
|
584
|
+
});
|
|
585
|
+
response += `\n\n**Executed Steps**\n`;
|
|
586
|
+
results.forEach(r => {
|
|
587
|
+
response += `${r.step}. **${r.tool}** ✓\n`;
|
|
588
|
+
});
|
|
589
|
+
response += `\n---\n\n**Actions**\n`;
|
|
590
|
+
response += `- Continue: \`replay({ action: 'step' })\`\n`;
|
|
591
|
+
response += `- Finish all: \`replay({ action: 'finish' })\`\n`;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
return response;
|
|
595
|
+
}
|
|
596
|
+
// =============================================================================
|
|
597
|
+
// Recorded Event Formatting
|
|
598
|
+
// =============================================================================
|
|
599
|
+
/** HH:MM:SS of an event timestamp, used as the per-event time marker. */
|
|
600
|
+
function eventTime(timestamp) {
|
|
601
|
+
return new Date(timestamp).toISOString().split('T')[1].split('.')[0];
|
|
602
|
+
}
|
|
603
|
+
/** `tag#id` / `tag` description of a keyboard or paste target. */
|
|
604
|
+
function describeTarget(targetInfo) {
|
|
605
|
+
if (!targetInfo)
|
|
606
|
+
return [];
|
|
607
|
+
const lines = [`Target: \`${targetInfo.tag}${targetInfo.id ? '#' + targetInfo.id : ''}\``];
|
|
608
|
+
if (targetInfo.selector) {
|
|
609
|
+
lines.push(`Selector: \`${targetInfo.selector}\` ✓`);
|
|
610
|
+
}
|
|
611
|
+
if (targetInfo.isInput) {
|
|
612
|
+
lines.push(`Type: **Input field**`);
|
|
613
|
+
}
|
|
614
|
+
return lines;
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Format recorded input events for human review.
|
|
618
|
+
*
|
|
619
|
+
* This is the `outputFormat: 'review'` implementation - a readable walk of what
|
|
620
|
+
* the recorder actually captured, showing both the coordinates and the selector
|
|
621
|
+
* it found for each interaction so a human can judge which one a command should
|
|
622
|
+
* use. Noise (mousemove, keyup) is dropped; every other event variant -
|
|
623
|
+
* including navigation, paste and comment events - gets its own entry.
|
|
624
|
+
*/
|
|
625
|
+
export function formatEventsForReview(events) {
|
|
626
|
+
const lines = [];
|
|
627
|
+
let eventNum = 0;
|
|
628
|
+
for (const event of events) {
|
|
629
|
+
// Comments the person typed during the recording - the most valuable
|
|
630
|
+
// context in a review dump, so they are never dropped.
|
|
631
|
+
if (isCommentEvent(event)) {
|
|
632
|
+
eventNum++;
|
|
633
|
+
const category = event.category || 'narrative';
|
|
634
|
+
const label = category === 'bug' ? 'COMMENT (BUG)'
|
|
635
|
+
: category === 'feature' ? 'COMMENT (FEATURE)'
|
|
636
|
+
: 'COMMENT';
|
|
637
|
+
lines.push(`### ${eventNum}. ${label}`);
|
|
638
|
+
lines.push(`Time: ${eventTime(event.timestamp)}`);
|
|
639
|
+
lines.push(`Note: "${event.text}"`);
|
|
640
|
+
if (event.attachedToEventIndex !== undefined) {
|
|
641
|
+
lines.push(`Attached to event index: ${event.attachedToEventIndex}`);
|
|
642
|
+
}
|
|
643
|
+
lines.push('');
|
|
644
|
+
continue;
|
|
645
|
+
}
|
|
646
|
+
// Page navigations / reloads that happened mid-recording.
|
|
647
|
+
if (isNavigationEvent(event)) {
|
|
648
|
+
eventNum++;
|
|
649
|
+
lines.push(`### ${eventNum}. ${event.type.toUpperCase()} to ${event.url}`);
|
|
650
|
+
lines.push(`Time: ${eventTime(event.timestamp)}`);
|
|
651
|
+
if (event.previousUrl) {
|
|
652
|
+
lines.push(`From: ${event.previousUrl}`);
|
|
653
|
+
}
|
|
654
|
+
lines.push('');
|
|
655
|
+
continue;
|
|
656
|
+
}
|
|
657
|
+
// Pasted text - the text matters more than the keystrokes that triggered it.
|
|
658
|
+
if (isPasteEvent(event)) {
|
|
659
|
+
eventNum++;
|
|
660
|
+
const text = event.text.length > 60 ? event.text.substring(0, 57) + '...' : event.text;
|
|
661
|
+
lines.push(`### ${eventNum}. PASTE`);
|
|
662
|
+
lines.push(`Time: ${eventTime(event.timestamp)}`);
|
|
663
|
+
lines.push(`Text: "${text}" (${event.text.length} chars)`);
|
|
664
|
+
lines.push(...describeTarget(event.targetInfo));
|
|
665
|
+
lines.push('');
|
|
666
|
+
continue;
|
|
667
|
+
}
|
|
668
|
+
if (isKeyboardEvent(event)) {
|
|
669
|
+
// Skip keyup for review
|
|
670
|
+
if (event.type === 'keyup')
|
|
671
|
+
continue;
|
|
672
|
+
eventNum++;
|
|
673
|
+
let keyDisplay = event.key;
|
|
674
|
+
if (event.modifiers) {
|
|
675
|
+
const mods = [];
|
|
676
|
+
if (event.modifiers.ctrl)
|
|
677
|
+
mods.push('Ctrl');
|
|
678
|
+
if (event.modifiers.alt)
|
|
679
|
+
mods.push('Alt');
|
|
680
|
+
if (event.modifiers.shift)
|
|
681
|
+
mods.push('Shift');
|
|
682
|
+
if (event.modifiers.meta)
|
|
683
|
+
mods.push('Cmd');
|
|
684
|
+
if (mods.length > 0)
|
|
685
|
+
keyDisplay = mods.join('+') + '+' + keyDisplay;
|
|
686
|
+
}
|
|
687
|
+
lines.push(`### ${eventNum}. KEY \`${keyDisplay}\``);
|
|
688
|
+
lines.push(`Time: ${eventTime(event.timestamp)}`);
|
|
689
|
+
lines.push(...describeTarget(event.targetInfo));
|
|
690
|
+
lines.push('');
|
|
691
|
+
continue;
|
|
692
|
+
}
|
|
693
|
+
if (!isMouseEvent(event))
|
|
694
|
+
continue;
|
|
695
|
+
// Skip pure mousemove events for review (too noisy)
|
|
696
|
+
if (event.type === 'mousemove')
|
|
697
|
+
continue;
|
|
698
|
+
eventNum++;
|
|
699
|
+
const coords = `(${event.x}, ${event.y})`;
|
|
700
|
+
const el = event.elementInfo;
|
|
701
|
+
lines.push(`### ${eventNum}. ${event.type.toUpperCase()} at ${coords}`);
|
|
702
|
+
lines.push(`Time: ${eventTime(event.timestamp)}`);
|
|
703
|
+
if (el) {
|
|
704
|
+
lines.push(`Element: \`${el.tag}${el.id ? '#' + el.id : ''}${el.className ? '.' + el.className.split(' ')[0] : ''}\``);
|
|
705
|
+
if (el.selector) {
|
|
706
|
+
lines.push(`Selector: \`${el.selector}\` ✓`);
|
|
707
|
+
}
|
|
708
|
+
else {
|
|
709
|
+
lines.push(`Selector: *(none available)*`);
|
|
710
|
+
}
|
|
711
|
+
if (el.isCanvas) {
|
|
712
|
+
lines.push(`Type: **Canvas/3D** - use coordinates`);
|
|
713
|
+
}
|
|
714
|
+
else if (el.isInteractive) {
|
|
715
|
+
lines.push(`Type: **Interactive** - selector recommended`);
|
|
716
|
+
}
|
|
717
|
+
if (el.text) {
|
|
718
|
+
lines.push(`Text: "${el.text.substring(0, 40)}${el.text.length > 40 ? '...' : ''}"`);
|
|
719
|
+
}
|
|
720
|
+
if (el.boundingBox) {
|
|
721
|
+
const bb = el.boundingBox;
|
|
722
|
+
lines.push(`Bounds: ${bb.width}x${bb.height} at (${bb.x}, ${bb.y})`);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (event.type === 'wheel') {
|
|
726
|
+
lines.push(`Scroll: deltaX=${event.deltaX || 0}, deltaY=${event.deltaY || 0}`);
|
|
727
|
+
}
|
|
728
|
+
lines.push('');
|
|
729
|
+
}
|
|
730
|
+
if (eventNum === 0) {
|
|
731
|
+
return '_No reviewable events were captured._';
|
|
732
|
+
}
|
|
733
|
+
return lines.join('\n');
|
|
734
|
+
}
|
|
735
|
+
// =============================================================================
|
|
736
|
+
// Insert Formatting
|
|
737
|
+
// =============================================================================
|
|
738
|
+
/**
|
|
739
|
+
* Format insert prompt (when no indices provided)
|
|
740
|
+
*/
|
|
741
|
+
export function formatInsertPrompt(sequenceName, commandsSincePause, currentStep, totalSteps) {
|
|
742
|
+
if (commandsSincePause.length === 0) {
|
|
743
|
+
return getFormattedResponse('REPLAY_NO_COMMANDS_SINCE_PAUSE', {});
|
|
744
|
+
}
|
|
745
|
+
let response = getFormattedResponse('REPLAY_INSERT_PROMPT', {
|
|
746
|
+
sequenceName,
|
|
747
|
+
commandCount: commandsSincePause.length
|
|
748
|
+
});
|
|
749
|
+
response += `\n\n**Commands recorded since pause:**\n`;
|
|
750
|
+
commandsSincePause.forEach((cmd) => {
|
|
751
|
+
response += `- [#${cmd.index}] **${cmd.tool}**`;
|
|
752
|
+
if (cmd.params && Object.keys(cmd.params).length > 0) {
|
|
753
|
+
const paramStr = JSON.stringify(cmd.params);
|
|
754
|
+
response += ` - ${paramStr.length > 50 ? paramStr.slice(0, 50) + '...' : paramStr}`;
|
|
755
|
+
}
|
|
756
|
+
response += `\n`;
|
|
757
|
+
});
|
|
758
|
+
response += `\n**Current position:** After step ${currentStep} of ${totalSteps}`;
|
|
759
|
+
response += `\n\n**Insert Options**\n\n`;
|
|
760
|
+
response += `**Insert all commands:**\n`;
|
|
761
|
+
response += `\`\`\`\nreplay({ action: 'insert', insertIndices: [${commandsSincePause.map(c => c.index).join(', ')}], overwrite: true })\n\`\`\`\n\n`;
|
|
762
|
+
response += `**Or select specific indices and optionally save as new sequence:**\n`;
|
|
763
|
+
response += `\`\`\`\nreplay({ action: 'insert', insertIndices: [${commandsSincePause[0]?.index || 0}], newName: 'updated-sequence' })\n\`\`\`\n`;
|
|
764
|
+
return response;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Format insert result
|
|
768
|
+
*/
|
|
769
|
+
export function formatInsertResult(sequenceName, sequenceId, insertedCount, insertAfter, newTotal, isOverwrite) {
|
|
770
|
+
let response;
|
|
771
|
+
if (isOverwrite) {
|
|
772
|
+
response = getFormattedResponse('REPLAY_INSERT_SUCCESS', {
|
|
773
|
+
sequenceName,
|
|
774
|
+
insertedCount,
|
|
775
|
+
insertAfter
|
|
776
|
+
});
|
|
777
|
+
response += `\n\n**New total:** ${newTotal} commands`;
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
response = getFormattedResponse('REPLAY_INSERT_NEW', {
|
|
781
|
+
sequenceName,
|
|
782
|
+
insertedCount
|
|
783
|
+
});
|
|
784
|
+
response += `\n\n**Inserted after step:** ${insertAfter}`;
|
|
785
|
+
response += `\n**Total commands:** ${newTotal}`;
|
|
786
|
+
}
|
|
787
|
+
// `export`, not `save` - the latter was removed from the action enum and a
|
|
788
|
+
// hint naming it sends the caller into a validation error.
|
|
789
|
+
response += `\n\nSave to disk: \`replay({ action: 'export', sequenceId: '${sequenceId}' })\``;
|
|
790
|
+
return response;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Format the result of adding a `conditional` step.
|
|
794
|
+
*/
|
|
795
|
+
export function formatConditionalAdded(info) {
|
|
796
|
+
const lines = [
|
|
797
|
+
`**Conditional added to "${info.sequenceName}"**`,
|
|
798
|
+
'',
|
|
799
|
+
`- **Step ${info.position + 1}** of ${info.totalSteps}`,
|
|
800
|
+
`- **If:** \`${info.condition}\``,
|
|
801
|
+
`- **Then run:** \`${info.thenSequence}\``,
|
|
802
|
+
];
|
|
803
|
+
lines.push('');
|
|
804
|
+
if (info.persistedTo) {
|
|
805
|
+
lines.push(`Saved to \`${info.persistedTo}\`.`);
|
|
806
|
+
}
|
|
807
|
+
else {
|
|
808
|
+
lines.push(`In memory only - save with \`replay({ action: 'export', name: '${info.sequenceName}' })\`.`);
|
|
809
|
+
}
|
|
810
|
+
lines.push(`The condition is evaluated at run time; if it does not hold, the step is skipped and the sequence continues.`);
|
|
811
|
+
return lines.join('\n');
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* What a sequence now declares, after `declare` has set it.
|
|
815
|
+
*
|
|
816
|
+
* Reads back the whole statement rather than just the change: each list
|
|
817
|
+
* replaces its field, so "what does this sequence declare now" is the only
|
|
818
|
+
* question the caller can act on.
|
|
819
|
+
*/
|
|
820
|
+
export function formatDeclarations(sequence, persistedTo) {
|
|
821
|
+
const connections = sequence.requiredConnections ?? [];
|
|
822
|
+
const sockets = sequence.requiredSockets ?? [];
|
|
823
|
+
const lines = [`**"${sequence.name}" declares**`, ''];
|
|
824
|
+
if (connections.length === 0) {
|
|
825
|
+
lines.push('- **Browsers:** none - the run brings up only its own connection');
|
|
826
|
+
}
|
|
827
|
+
else {
|
|
828
|
+
lines.push('- **Browsers:**');
|
|
829
|
+
for (const decl of connections) {
|
|
830
|
+
const notes = [
|
|
831
|
+
decl.profile ? `profile \`${decl.profile}\`` : null,
|
|
832
|
+
decl.role,
|
|
833
|
+
decl.url ? `opens ${decl.url}` : null,
|
|
834
|
+
decl.profile && decl.forceNewInstance !== true ? 'reuses the Chrome already on that profile' : null,
|
|
835
|
+
!decl.profile && decl.forceNewInstance === false ? 'may share an existing browser' : null,
|
|
836
|
+
].filter(Boolean);
|
|
837
|
+
lines.push(` - \`${decl.reference}\`${notes.length ? ` - ${notes.join('; ')}` : ''}`);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
lines.push(sockets.length === 0
|
|
841
|
+
? '- **Sockets:** none declared - socket health is only checked when a run asks for it'
|
|
842
|
+
: `- **Sockets:** ${sockets.map(s => `\`${s}\``).join(', ')} - checked on every run, without asking`);
|
|
843
|
+
const tags = sequence.tags ?? [];
|
|
844
|
+
lines.push(tags.length === 0
|
|
845
|
+
? "- **Tags:** none - it runs in every `runAll`, and counts as untagged in the summary split"
|
|
846
|
+
: `- **Tags:** ${tags.map(t => `\`${t}\``).join(', ')} - selectable with \`runAll({ tags: [...] })\``);
|
|
847
|
+
lines.push('');
|
|
848
|
+
lines.push(persistedTo
|
|
849
|
+
? `Saved to \`${persistedTo}\`.`
|
|
850
|
+
: `In memory only - save with \`replay({ action: 'export', name: '${sequence.name}' })\`.`);
|
|
851
|
+
if (connections.some(d => d.profile)) {
|
|
852
|
+
lines.push('A profile-bearing reference cannot be rebound with `connections` at run time: the profile is the identity, and pointing it at another browser would pass while testing the wrong one.');
|
|
853
|
+
}
|
|
854
|
+
return lines.join('\n');
|
|
855
|
+
}
|
|
856
|
+
//# sourceMappingURL=replay-formatters.js.map
|