gsd-pi 2.20.0 → 2.22.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/README.md +12 -0
- package/dist/cli.js +21 -18
- package/dist/help-text.d.ts +2 -0
- package/dist/help-text.js +47 -0
- package/dist/loader.js +2 -16
- package/dist/mcp-server.d.ts +18 -0
- package/dist/mcp-server.js +53 -0
- package/dist/onboarding.d.ts +0 -6
- package/dist/onboarding.js +0 -28
- package/dist/resources/agents/javascript-pro.md +280 -0
- package/dist/resources/agents/typescript-pro.md +255 -0
- package/dist/resources/extensions/bg-shell/index.ts +14 -2
- package/dist/resources/extensions/bg-shell/utilities.ts +14 -0
- package/dist/resources/extensions/browser-tools/{core.js → core.ts} +329 -190
- package/dist/resources/extensions/gsd/auto-dashboard.ts +2 -1
- package/dist/resources/extensions/gsd/auto-prompts.ts +42 -1
- package/dist/resources/extensions/gsd/auto-worktree.ts +35 -2
- package/dist/resources/extensions/gsd/auto.ts +116 -10
- package/dist/resources/extensions/gsd/claude-import.ts +656 -0
- package/dist/resources/extensions/gsd/collision-diagnostics.ts +332 -0
- package/dist/resources/extensions/gsd/commands.ts +60 -7
- package/dist/resources/extensions/gsd/diff-context.ts +220 -0
- package/dist/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +2 -1
- package/dist/resources/extensions/gsd/doctor.ts +12 -4
- package/dist/resources/extensions/gsd/file-watcher.ts +97 -0
- package/dist/resources/extensions/gsd/files.ts +1 -1
- package/dist/resources/extensions/gsd/forensics.ts +596 -0
- package/dist/resources/extensions/gsd/git-service.ts +2 -1
- package/dist/resources/extensions/gsd/github-client.ts +235 -0
- package/dist/resources/extensions/gsd/gitignore.ts +1 -0
- package/dist/resources/extensions/gsd/marketplace-discovery.ts +507 -0
- package/dist/resources/extensions/gsd/mcp-server.ts +87 -0
- package/dist/resources/extensions/gsd/namespaced-registry.ts +467 -0
- package/dist/resources/extensions/gsd/namespaced-resolver.ts +307 -0
- package/dist/resources/extensions/gsd/plugin-importer.ts +410 -0
- package/dist/resources/extensions/gsd/preferences.ts +14 -3
- package/dist/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +71 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/system.md +12 -3
- package/dist/resources/extensions/gsd/roadmap-slices.ts +1 -1
- package/dist/resources/extensions/gsd/session-forensics.ts +5 -5
- package/dist/resources/extensions/gsd/tests/claude-import-tui.test.ts +351 -0
- package/dist/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
- package/dist/resources/extensions/gsd/tests/context-compression.test.ts +13 -0
- package/dist/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
- package/dist/resources/extensions/gsd/tests/doctor-git.test.ts +118 -0
- package/dist/resources/extensions/gsd/tests/marketplace-discovery.test.ts +202 -0
- package/dist/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
- package/dist/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
- package/dist/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
- package/dist/resources/extensions/gsd/tests/none-mode-gates.test.ts +105 -0
- package/dist/resources/extensions/gsd/tests/plugin-importer-live.test.ts +481 -0
- package/dist/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
- package/dist/resources/extensions/gsd/tests/preferences-git.test.ts +21 -2
- package/dist/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +8 -1
- package/dist/resources/extensions/gsd/tests/visualizer-data.test.ts +11 -0
- package/dist/resources/extensions/gsd/tests/worktree-bugfix.test.ts +120 -0
- package/dist/resources/extensions/gsd/token-counter.ts +45 -0
- package/dist/resources/extensions/gsd/visualizer-data.ts +2 -2
- package/dist/resources/extensions/gsd/worktree-manager.ts +29 -1
- package/dist/resources/extensions/gsd/worktree.ts +3 -0
- package/dist/resources/extensions/mcporter/index.ts +90 -7
- package/dist/resources/extensions/search-the-web/native-search.ts +2 -0
- package/dist/resources/extensions/search-the-web/tool-fetch-page.ts +9 -1
- package/dist/resources/extensions/search-the-web/url-utils.ts +35 -1
- package/dist/resources/extensions/shared/terminal.ts +1 -1
- package/dist/resources/extensions/universal-config/discovery.ts +4 -0
- package/dist/resources/extensions/universal-config/format.ts +35 -4
- package/dist/resources/extensions/universal-config/index.ts +5 -3
- package/dist/resources/extensions/universal-config/scanners.ts +65 -2
- package/dist/resources/extensions/universal-config/tests/discovery.test.ts +9 -1
- package/dist/resources/extensions/universal-config/tests/format.test.ts +22 -6
- package/dist/resources/extensions/universal-config/tests/scanners.test.ts +18 -0
- package/dist/resources/extensions/universal-config/types.ts +20 -1
- package/dist/resources/skills/lint/SKILL.md +141 -0
- package/dist/resources/skills/review/SKILL.md +214 -0
- package/dist/resources/skills/test/SKILL.md +201 -0
- package/dist/tool-bootstrap.js +2 -1
- package/dist/wizard.js +2 -0
- package/package.json +12 -7
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js +12 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +12 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/LICENSE +201 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/README.md +9 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-cjs/index.js +762 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/build-abort-error.js +19 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/constants.js +1 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/get-transformed-headers.js +9 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/index.js +3 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http-handler.js +230 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-manager.js +87 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-connection-pool.js +32 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/node-http2-handler.js +169 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/readable.mock.js +21 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/server.mock.js +88 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-connection-timeout.js +36 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-request-timeout.js +21 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-keep-alive.js +22 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/set-socket-timeout.js +23 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/collector.js +8 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/index.js +41 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/stream-collector/readable.mock.js +21 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/timing.js +4 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-es/write-request-body.js +63 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/build-abort-error.d.ts +10 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/constants.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/get-transformed-headers.d.ts +4 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/index.d.ts +3 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http-handler.d.ts +46 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-manager.d.ts +24 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-connection-pool.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/node-http2-handler.d.ts +63 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/server.mock.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-connection-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-request-timeout.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-keep-alive.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/set-socket-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/collector.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/index.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/stream-collector/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/timing.d.ts +8 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/build-abort-error.d.ts +10 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/constants.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/get-transformed-headers.d.ts +4 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/index.d.ts +3 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http-handler.d.ts +46 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-manager.d.ts +24 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-connection-pool.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/node-http2-handler.d.ts +63 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/server.mock.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-connection-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-request-timeout.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-keep-alive.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/set-socket-timeout.d.ts +2 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/collector.d.ts +5 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/index.d.ts +6 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/stream-collector/readable.mock.d.ts +13 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/timing.d.ts +8 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/ts3.4/write-request-body.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/dist-types/write-request-body.d.ts +12 -0
- package/packages/pi-ai/node_modules/@smithy/node-http-handler/package.json +68 -0
- package/packages/pi-ai/package.json +3 -0
- package/packages/pi-ai/pnpm-lock.yaml +2022 -0
- package/packages/pi-ai/src/providers/azure-openai-responses.ts +12 -1
- package/packages/pi-ai/src/providers/openai-responses.ts +12 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +12 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +113 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.js +42 -0
- package/packages/pi-coding-agent/dist/core/extensions/project-trust.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.js +18 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +114 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +8 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +23 -9
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +67 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/pnpm-lock.yaml +454 -0
- package/packages/pi-coding-agent/scripts/copy-assets.cjs +24 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.test.ts +141 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +14 -1
- package/packages/pi-coding-agent/src/core/extensions/project-trust.ts +51 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +132 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.ts +20 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/login-dialog.ts +7 -2
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +98 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +24 -9
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +2 -2
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/package.json +3 -1
- package/packages/pi-tui/src/tui.ts +2 -2
- package/src/resources/agents/javascript-pro.md +280 -0
- package/src/resources/agents/typescript-pro.md +255 -0
- package/src/resources/extensions/bg-shell/index.ts +14 -2
- package/src/resources/extensions/bg-shell/utilities.ts +14 -0
- package/src/resources/extensions/browser-tools/{core.js → core.ts} +329 -190
- package/src/resources/extensions/gsd/auto-dashboard.ts +2 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +42 -1
- package/src/resources/extensions/gsd/auto-worktree.ts +35 -2
- package/src/resources/extensions/gsd/auto.ts +116 -10
- package/src/resources/extensions/gsd/claude-import.ts +656 -0
- package/src/resources/extensions/gsd/collision-diagnostics.ts +332 -0
- package/src/resources/extensions/gsd/commands.ts +60 -7
- package/src/resources/extensions/gsd/diff-context.ts +220 -0
- package/src/resources/extensions/gsd/docs/claude-marketplace-import.md +214 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +2 -1
- package/src/resources/extensions/gsd/doctor.ts +12 -4
- package/src/resources/extensions/gsd/file-watcher.ts +97 -0
- package/src/resources/extensions/gsd/files.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +596 -0
- package/src/resources/extensions/gsd/git-service.ts +2 -1
- package/src/resources/extensions/gsd/github-client.ts +235 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -0
- package/src/resources/extensions/gsd/marketplace-discovery.ts +507 -0
- package/src/resources/extensions/gsd/mcp-server.ts +87 -0
- package/src/resources/extensions/gsd/namespaced-registry.ts +467 -0
- package/src/resources/extensions/gsd/namespaced-resolver.ts +307 -0
- package/src/resources/extensions/gsd/plugin-importer.ts +410 -0
- package/src/resources/extensions/gsd/preferences.ts +14 -3
- package/src/resources/extensions/gsd/prompts/execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +71 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/system.md +12 -3
- package/src/resources/extensions/gsd/roadmap-slices.ts +1 -1
- package/src/resources/extensions/gsd/session-forensics.ts +5 -5
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +351 -0
- package/src/resources/extensions/gsd/tests/collision-diagnostics.test.ts +705 -0
- package/src/resources/extensions/gsd/tests/context-compression.test.ts +13 -0
- package/src/resources/extensions/gsd/tests/diff-context.test.ts +136 -0
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +118 -0
- package/src/resources/extensions/gsd/tests/marketplace-discovery.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/marketplace-test-fixtures.ts +91 -0
- package/src/resources/extensions/gsd/tests/namespaced-registry.test.ts +1027 -0
- package/src/resources/extensions/gsd/tests/namespaced-resolver.test.ts +671 -0
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/plugin-importer-live.test.ts +481 -0
- package/src/resources/extensions/gsd/tests/plugin-importer.test.ts +1383 -0
- package/src/resources/extensions/gsd/tests/preferences-git.test.ts +21 -2
- package/src/resources/extensions/gsd/tests/preferences-schema-validation.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +120 -0
- package/src/resources/extensions/gsd/token-counter.ts +45 -0
- package/src/resources/extensions/gsd/visualizer-data.ts +2 -2
- package/src/resources/extensions/gsd/worktree-manager.ts +29 -1
- package/src/resources/extensions/gsd/worktree.ts +3 -0
- package/src/resources/extensions/mcporter/index.ts +90 -7
- package/src/resources/extensions/search-the-web/native-search.ts +2 -0
- package/src/resources/extensions/search-the-web/tool-fetch-page.ts +9 -1
- package/src/resources/extensions/search-the-web/url-utils.ts +35 -1
- package/src/resources/extensions/shared/terminal.ts +1 -1
- package/src/resources/extensions/universal-config/discovery.ts +4 -0
- package/src/resources/extensions/universal-config/format.ts +35 -4
- package/src/resources/extensions/universal-config/index.ts +5 -3
- package/src/resources/extensions/universal-config/scanners.ts +65 -2
- package/src/resources/extensions/universal-config/tests/discovery.test.ts +9 -1
- package/src/resources/extensions/universal-config/tests/format.test.ts +22 -6
- package/src/resources/extensions/universal-config/tests/scanners.test.ts +18 -0
- package/src/resources/extensions/universal-config/types.ts +20 -1
- package/src/resources/skills/lint/SKILL.md +141 -0
- package/src/resources/skills/review/SKILL.md +214 -0
- package/src/resources/skills/test/SKILL.md +201 -0
- package/dist/resources/extensions/browser-tools/core.d.ts +0 -205
- package/src/resources/extensions/browser-tools/core.d.ts +0 -205
|
@@ -4,7 +4,171 @@
|
|
|
4
4
|
* Kept free of pi-specific imports so it can be exercised with node:test.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Interfaces & Types
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
export interface ActionTimeline {
|
|
12
|
+
limit: number;
|
|
13
|
+
nextId: number;
|
|
14
|
+
entries: ActionEntry[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ActionEntry {
|
|
18
|
+
id: number;
|
|
19
|
+
tool: string;
|
|
20
|
+
paramsSummary: string;
|
|
21
|
+
startedAt: number;
|
|
22
|
+
finishedAt: number | null;
|
|
23
|
+
status: string;
|
|
24
|
+
beforeUrl: string;
|
|
25
|
+
afterUrl: string;
|
|
26
|
+
verificationSummary?: string;
|
|
27
|
+
warningSummary?: string;
|
|
28
|
+
diffSummary?: string;
|
|
29
|
+
changed?: boolean;
|
|
30
|
+
error?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ActionPartial {
|
|
34
|
+
tool: string;
|
|
35
|
+
paramsSummary?: string;
|
|
36
|
+
startedAt?: number;
|
|
37
|
+
beforeUrl?: string;
|
|
38
|
+
afterUrl?: string;
|
|
39
|
+
verificationSummary?: string;
|
|
40
|
+
warningSummary?: string;
|
|
41
|
+
diffSummary?: string;
|
|
42
|
+
changed?: boolean;
|
|
43
|
+
error?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ActionUpdates {
|
|
47
|
+
finishedAt?: number;
|
|
48
|
+
status?: string;
|
|
49
|
+
afterUrl?: string;
|
|
50
|
+
verificationSummary?: string;
|
|
51
|
+
warningSummary?: string;
|
|
52
|
+
diffSummary?: string;
|
|
53
|
+
changed?: boolean;
|
|
54
|
+
error?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface DiffResult {
|
|
58
|
+
changed: boolean;
|
|
59
|
+
changes: Array<{ type: string; before: unknown; after: unknown }>;
|
|
60
|
+
summary: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface Threshold {
|
|
64
|
+
op: string;
|
|
65
|
+
n: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface PageRegistry {
|
|
69
|
+
pages: PageEntry[];
|
|
70
|
+
activePageId: number | null;
|
|
71
|
+
nextId: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface PageEntry {
|
|
75
|
+
id: number;
|
|
76
|
+
page: any;
|
|
77
|
+
title: string;
|
|
78
|
+
url: string;
|
|
79
|
+
opener: number | null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface PageListEntry {
|
|
83
|
+
id: number;
|
|
84
|
+
title: string;
|
|
85
|
+
url: string;
|
|
86
|
+
opener: number | null;
|
|
87
|
+
isActive: boolean;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface SnapshotModeConfig {
|
|
91
|
+
tags: string[];
|
|
92
|
+
roles: string[];
|
|
93
|
+
selectors: string[];
|
|
94
|
+
ariaAttributes: string[];
|
|
95
|
+
useInteractiveFilter: boolean;
|
|
96
|
+
visibleOnly?: boolean;
|
|
97
|
+
containerExpand?: boolean;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface AssertionCheckResult {
|
|
101
|
+
name: string;
|
|
102
|
+
passed: boolean;
|
|
103
|
+
actual: unknown;
|
|
104
|
+
expected: unknown;
|
|
105
|
+
selector?: string;
|
|
106
|
+
text?: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface AssertionEvaluation {
|
|
110
|
+
verified: boolean;
|
|
111
|
+
checks: AssertionCheckResult[];
|
|
112
|
+
summary: string;
|
|
113
|
+
agentHint: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface WaitValidationError {
|
|
117
|
+
error: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface BatchStepResult {
|
|
121
|
+
ok: boolean;
|
|
122
|
+
stopReason: string | null;
|
|
123
|
+
failedStepIndex: number | null;
|
|
124
|
+
stepResults: unknown[];
|
|
125
|
+
summary: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface FormattedTimeline {
|
|
129
|
+
entries: Array<{
|
|
130
|
+
id: number | null;
|
|
131
|
+
tool: string;
|
|
132
|
+
status: string;
|
|
133
|
+
durationMs: number | null;
|
|
134
|
+
beforeUrl: string;
|
|
135
|
+
afterUrl: string;
|
|
136
|
+
line: string;
|
|
137
|
+
}>;
|
|
138
|
+
retained: number;
|
|
139
|
+
totalRecorded: number;
|
|
140
|
+
bounded: boolean;
|
|
141
|
+
summary: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface FailureHypothesis {
|
|
145
|
+
hasFailures: boolean;
|
|
146
|
+
categories: string[];
|
|
147
|
+
summary: string;
|
|
148
|
+
signals: Array<{ category: string; source: string; detail: string }>;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface SessionSummary {
|
|
152
|
+
counts: {
|
|
153
|
+
pages: number;
|
|
154
|
+
actions: { total: number; retained: number; success: number; error: number; running: number };
|
|
155
|
+
waits: { total: number; success: number; error: number; running: number };
|
|
156
|
+
assertions: { total: number; passed: number; failed: number; running: number };
|
|
157
|
+
consoleErrors: number;
|
|
158
|
+
failedRequests: number;
|
|
159
|
+
dialogs: number;
|
|
160
|
+
};
|
|
161
|
+
activePage: { id: number | null; title: string; url: string } | null;
|
|
162
|
+
caveats: string[];
|
|
163
|
+
failureHypothesis: FailureHypothesis;
|
|
164
|
+
summary: string;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Action Timeline
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
export function createActionTimeline(limit = 60): ActionTimeline {
|
|
8
172
|
return {
|
|
9
173
|
limit,
|
|
10
174
|
nextId: 1,
|
|
@@ -12,8 +176,8 @@ export function createActionTimeline(limit = 60) {
|
|
|
12
176
|
};
|
|
13
177
|
}
|
|
14
178
|
|
|
15
|
-
export function beginAction(timeline, partial) {
|
|
16
|
-
const entry = {
|
|
179
|
+
export function beginAction(timeline: ActionTimeline, partial: ActionPartial): ActionEntry {
|
|
180
|
+
const entry: ActionEntry = {
|
|
17
181
|
id: timeline.nextId++,
|
|
18
182
|
tool: partial.tool,
|
|
19
183
|
paramsSummary: partial.paramsSummary ?? "",
|
|
@@ -35,7 +199,7 @@ export function beginAction(timeline, partial) {
|
|
|
35
199
|
return entry;
|
|
36
200
|
}
|
|
37
201
|
|
|
38
|
-
export function finishAction(timeline, actionId, updates = {}) {
|
|
202
|
+
export function finishAction(timeline: ActionTimeline, actionId: number, updates: ActionUpdates = {}): ActionEntry | null {
|
|
39
203
|
const entry = timeline.entries.find((item) => item.id === actionId);
|
|
40
204
|
if (!entry) return null;
|
|
41
205
|
Object.assign(entry, updates, {
|
|
@@ -51,14 +215,14 @@ export function finishAction(timeline, actionId, updates = {}) {
|
|
|
51
215
|
return entry;
|
|
52
216
|
}
|
|
53
217
|
|
|
54
|
-
export function findAction(timeline, actionId) {
|
|
218
|
+
export function findAction(timeline: ActionTimeline, actionId: number): ActionEntry | null {
|
|
55
219
|
return timeline.entries.find((item) => item.id === actionId) ?? null;
|
|
56
220
|
}
|
|
57
221
|
|
|
58
|
-
export function toActionParamsSummary(params) {
|
|
222
|
+
export function toActionParamsSummary(params: unknown): string {
|
|
59
223
|
if (!params || typeof params !== "object") return "";
|
|
60
|
-
const entries = [];
|
|
61
|
-
for (const [key, value] of Object.entries(params)) {
|
|
224
|
+
const entries: string[] = [];
|
|
225
|
+
for (const [key, value] of Object.entries(params as Record<string, unknown>)) {
|
|
62
226
|
if (value === undefined || value === null) continue;
|
|
63
227
|
if (typeof value === "string") {
|
|
64
228
|
entries.push(`${key}=${JSON.stringify(value.length > 60 ? `${value.slice(0, 57)}...` : value)}`);
|
|
@@ -77,8 +241,22 @@ export function toActionParamsSummary(params) {
|
|
|
77
241
|
return entries.slice(0, 6).join(", ");
|
|
78
242
|
}
|
|
79
243
|
|
|
80
|
-
|
|
81
|
-
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
// Compact State Diffing
|
|
246
|
+
// ---------------------------------------------------------------------------
|
|
247
|
+
|
|
248
|
+
interface CompactStateForDiff {
|
|
249
|
+
url?: string;
|
|
250
|
+
title?: string;
|
|
251
|
+
focus?: string;
|
|
252
|
+
dialog?: { count?: number; title?: string };
|
|
253
|
+
counts?: Record<string, number>;
|
|
254
|
+
headings?: string[];
|
|
255
|
+
bodyText?: string;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function diffCompactStates(before: CompactStateForDiff | null | undefined, after: CompactStateForDiff | null | undefined): DiffResult {
|
|
259
|
+
const changes: Array<{ type: string; before: unknown; after: unknown }> = [];
|
|
82
260
|
if (!before || !after) {
|
|
83
261
|
return {
|
|
84
262
|
changed: false,
|
|
@@ -159,11 +337,15 @@ export function diffCompactStates(before, after) {
|
|
|
159
337
|
return { changed, changes, summary };
|
|
160
338
|
}
|
|
161
339
|
|
|
162
|
-
|
|
340
|
+
// ---------------------------------------------------------------------------
|
|
341
|
+
// String helpers
|
|
342
|
+
// ---------------------------------------------------------------------------
|
|
343
|
+
|
|
344
|
+
function normalizeString(value: unknown): string {
|
|
163
345
|
return String(value ?? "").trim();
|
|
164
346
|
}
|
|
165
347
|
|
|
166
|
-
export function includesNeedle(haystack, needle) {
|
|
348
|
+
export function includesNeedle(haystack: string, needle: string): boolean {
|
|
167
349
|
return normalizeString(haystack).toLowerCase().includes(normalizeString(needle).toLowerCase());
|
|
168
350
|
}
|
|
169
351
|
|
|
@@ -173,10 +355,8 @@ export function includesNeedle(haystack, needle) {
|
|
|
173
355
|
|
|
174
356
|
/**
|
|
175
357
|
* Parse a threshold expression like ">=3", "==0", "<5", or bare "3" (defaults to ">=").
|
|
176
|
-
* @param {string} value
|
|
177
|
-
* @returns {{ op: string, n: number } | null} — null if malformed
|
|
178
358
|
*/
|
|
179
|
-
export function parseThreshold(value) {
|
|
359
|
+
export function parseThreshold(value: string | null | undefined): Threshold | null {
|
|
180
360
|
if (value == null) return null;
|
|
181
361
|
const str = String(value).trim();
|
|
182
362
|
if (str === "") return null;
|
|
@@ -189,11 +369,8 @@ export function parseThreshold(value) {
|
|
|
189
369
|
|
|
190
370
|
/**
|
|
191
371
|
* Evaluate whether a count meets a parsed threshold.
|
|
192
|
-
* @param {number} count
|
|
193
|
-
* @param {{ op: string, n: number }} threshold
|
|
194
|
-
* @returns {boolean}
|
|
195
372
|
*/
|
|
196
|
-
export function meetsThreshold(count, threshold) {
|
|
373
|
+
export function meetsThreshold(count: number, threshold: Threshold): boolean {
|
|
197
374
|
switch (threshold.op) {
|
|
198
375
|
case ">=": return count >= threshold.n;
|
|
199
376
|
case "<=": return count <= threshold.n;
|
|
@@ -207,12 +384,12 @@ export function meetsThreshold(count, threshold) {
|
|
|
207
384
|
/**
|
|
208
385
|
* Filter entries that occurred at or after a given action's start time.
|
|
209
386
|
* If sinceActionId is missing or the action isn't found, returns all entries.
|
|
210
|
-
* @param {Array<{ timestamp?: number }>} entries
|
|
211
|
-
* @param {number | undefined} sinceActionId
|
|
212
|
-
* @param {{ entries: Array<{ id: number, startedAt: number }> }} timeline
|
|
213
|
-
* @returns {Array}
|
|
214
387
|
*/
|
|
215
|
-
export function getEntriesSince(
|
|
388
|
+
export function getEntriesSince(
|
|
389
|
+
entries: Array<{ timestamp?: number }>,
|
|
390
|
+
sinceActionId: number | undefined,
|
|
391
|
+
timeline: ActionTimeline,
|
|
392
|
+
): Array<{ timestamp?: number }> {
|
|
216
393
|
if (!entries || !Array.isArray(entries)) return [];
|
|
217
394
|
if (sinceActionId == null || !timeline) return entries;
|
|
218
395
|
const action = findAction(timeline, sinceActionId);
|
|
@@ -221,8 +398,34 @@ export function getEntriesSince(entries, sinceActionId, timeline) {
|
|
|
221
398
|
return entries.filter((e) => (e.timestamp ?? 0) >= since);
|
|
222
399
|
}
|
|
223
400
|
|
|
224
|
-
|
|
225
|
-
|
|
401
|
+
// ---------------------------------------------------------------------------
|
|
402
|
+
// Assertion Evaluation
|
|
403
|
+
// ---------------------------------------------------------------------------
|
|
404
|
+
|
|
405
|
+
interface AssertionCheckInput {
|
|
406
|
+
kind: string;
|
|
407
|
+
selector?: string;
|
|
408
|
+
value?: string;
|
|
409
|
+
text?: string;
|
|
410
|
+
checked?: boolean;
|
|
411
|
+
sinceActionId?: number;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
interface AssertionState {
|
|
415
|
+
url?: string;
|
|
416
|
+
title?: string;
|
|
417
|
+
bodyText?: string;
|
|
418
|
+
focus?: string;
|
|
419
|
+
selectorStates?: Record<string, { visible?: boolean; value?: string; checked?: boolean | null }>;
|
|
420
|
+
consoleEntries?: Array<{ type?: string; text?: string; message?: string; timestamp?: number }>;
|
|
421
|
+
networkEntries?: Array<{ type?: string; url?: string; status?: number; failed?: boolean; timestamp?: number }>;
|
|
422
|
+
allConsoleEntries?: Array<{ type?: string; text?: string; message?: string; timestamp?: number }>;
|
|
423
|
+
allNetworkEntries?: Array<{ type?: string; url?: string; status?: number; failed?: boolean; timestamp?: number }>;
|
|
424
|
+
actionTimeline?: ActionTimeline | null;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export function evaluateAssertionChecks({ checks, state }: { checks: AssertionCheckInput[]; state: AssertionState }): AssertionEvaluation {
|
|
428
|
+
const results: AssertionCheckResult[] = [];
|
|
226
429
|
const selectorStates = state.selectorStates ?? {};
|
|
227
430
|
const consoleEntries = state.consoleEntries ?? [];
|
|
228
431
|
const networkEntries = state.networkEntries ?? [];
|
|
@@ -233,29 +436,29 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
233
436
|
for (const check of checks) {
|
|
234
437
|
const selectorState = check.selector ? selectorStates[check.selector] ?? null : null;
|
|
235
438
|
let passed = false;
|
|
236
|
-
let actual;
|
|
237
|
-
let expected;
|
|
439
|
+
let actual: unknown;
|
|
440
|
+
let expected: unknown;
|
|
238
441
|
|
|
239
442
|
switch (check.kind) {
|
|
240
443
|
case "url_contains":
|
|
241
444
|
actual = state.url ?? "";
|
|
242
445
|
expected = check.value ?? "";
|
|
243
|
-
passed = includesNeedle(actual, expected);
|
|
446
|
+
passed = includesNeedle(actual as string, expected as string);
|
|
244
447
|
break;
|
|
245
448
|
case "title_contains":
|
|
246
449
|
actual = state.title ?? "";
|
|
247
450
|
expected = check.value ?? "";
|
|
248
|
-
passed = includesNeedle(actual, expected);
|
|
451
|
+
passed = includesNeedle(actual as string, expected as string);
|
|
249
452
|
break;
|
|
250
453
|
case "text_visible":
|
|
251
454
|
actual = state.bodyText ?? "";
|
|
252
455
|
expected = check.text ?? "";
|
|
253
|
-
passed = includesNeedle(actual, expected);
|
|
456
|
+
passed = includesNeedle(actual as string, expected as string);
|
|
254
457
|
break;
|
|
255
458
|
case "text_not_visible":
|
|
256
459
|
actual = state.bodyText ?? "";
|
|
257
460
|
expected = check.text ?? "";
|
|
258
|
-
passed = !includesNeedle(actual, expected);
|
|
461
|
+
passed = !includesNeedle(actual as string, expected as string);
|
|
259
462
|
break;
|
|
260
463
|
case "selector_visible":
|
|
261
464
|
actual = selectorState?.visible ?? false;
|
|
@@ -275,12 +478,12 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
275
478
|
case "value_contains":
|
|
276
479
|
actual = selectorState?.value ?? "";
|
|
277
480
|
expected = check.value ?? "";
|
|
278
|
-
passed = includesNeedle(actual, expected);
|
|
481
|
+
passed = includesNeedle(actual as string, expected as string);
|
|
279
482
|
break;
|
|
280
483
|
case "focused_matches":
|
|
281
484
|
actual = state.focus ?? "";
|
|
282
485
|
expected = check.value ?? "";
|
|
283
|
-
passed = includesNeedle(actual, expected);
|
|
486
|
+
passed = includesNeedle(actual as string, expected as string);
|
|
284
487
|
break;
|
|
285
488
|
case "checked_equals":
|
|
286
489
|
actual = selectorState?.checked ?? null;
|
|
@@ -301,8 +504,8 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
301
504
|
// --- S02: New structured network/console assertion kinds ---
|
|
302
505
|
|
|
303
506
|
case "request_url_seen": {
|
|
304
|
-
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline);
|
|
305
|
-
const matches = filtered.filter((e) => includesNeedle(e.url ?? "", check.text ?? ""));
|
|
507
|
+
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline!);
|
|
508
|
+
const matches = (filtered as typeof allNetworkEntries).filter((e) => includesNeedle(e.url ?? "", check.text ?? ""));
|
|
306
509
|
actual = matches.length > 0;
|
|
307
510
|
expected = true;
|
|
308
511
|
passed = actual === true;
|
|
@@ -310,9 +513,9 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
310
513
|
}
|
|
311
514
|
|
|
312
515
|
case "response_status": {
|
|
313
|
-
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline);
|
|
314
|
-
const statusNum = parseInt(check.value
|
|
315
|
-
const matches = filtered.filter(
|
|
516
|
+
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline!);
|
|
517
|
+
const statusNum = parseInt(check.value!, 10);
|
|
518
|
+
const matches = (filtered as typeof allNetworkEntries).filter(
|
|
316
519
|
(e) => includesNeedle(e.url ?? "", check.text ?? "") && typeof e.status === "number" && e.status === statusNum
|
|
317
520
|
);
|
|
318
521
|
actual = matches.length > 0 ? `found (status=${matches[0].status})` : `not found`;
|
|
@@ -322,8 +525,8 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
322
525
|
}
|
|
323
526
|
|
|
324
527
|
case "console_message_matches": {
|
|
325
|
-
const filtered = getEntriesSince(allConsoleEntries, check.sinceActionId, actionTimeline);
|
|
326
|
-
const matches = filtered.filter((e) => includesNeedle(e.text ?? "", check.text ?? ""));
|
|
528
|
+
const filtered = getEntriesSince(allConsoleEntries, check.sinceActionId, actionTimeline!);
|
|
529
|
+
const matches = (filtered as typeof allConsoleEntries).filter((e) => includesNeedle(e.text ?? "", check.text ?? ""));
|
|
327
530
|
actual = matches.length > 0;
|
|
328
531
|
expected = true;
|
|
329
532
|
passed = actual === true;
|
|
@@ -331,8 +534,8 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
331
534
|
}
|
|
332
535
|
|
|
333
536
|
case "network_count": {
|
|
334
|
-
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline);
|
|
335
|
-
const matches = filtered.filter((e) => includesNeedle(e.url ?? "", check.text ?? ""));
|
|
537
|
+
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline!);
|
|
538
|
+
const matches = (filtered as typeof allNetworkEntries).filter((e) => includesNeedle(e.url ?? "", check.text ?? ""));
|
|
336
539
|
const threshold = parseThreshold(check.value);
|
|
337
540
|
if (!threshold) {
|
|
338
541
|
actual = `invalid threshold: ${check.value}`;
|
|
@@ -347,8 +550,8 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
347
550
|
}
|
|
348
551
|
|
|
349
552
|
case "console_count": {
|
|
350
|
-
const filtered = getEntriesSince(allConsoleEntries, check.sinceActionId, actionTimeline);
|
|
351
|
-
const matches = filtered.filter((e) => includesNeedle(e.text ?? "", check.text ?? ""));
|
|
553
|
+
const filtered = getEntriesSince(allConsoleEntries, check.sinceActionId, actionTimeline!);
|
|
554
|
+
const matches = (filtered as typeof allConsoleEntries).filter((e) => includesNeedle(e.text ?? "", check.text ?? ""));
|
|
352
555
|
const threshold = parseThreshold(check.value);
|
|
353
556
|
if (!threshold) {
|
|
354
557
|
actual = `invalid threshold: ${check.value}`;
|
|
@@ -363,8 +566,8 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
363
566
|
}
|
|
364
567
|
|
|
365
568
|
case "no_console_errors_since": {
|
|
366
|
-
const filtered = getEntriesSince(allConsoleEntries, check.sinceActionId, actionTimeline);
|
|
367
|
-
const errors = filtered.filter((e) => e.type === "error" || e.type === "pageerror");
|
|
569
|
+
const filtered = getEntriesSince(allConsoleEntries, check.sinceActionId, actionTimeline!);
|
|
570
|
+
const errors = (filtered as typeof allConsoleEntries).filter((e) => e.type === "error" || e.type === "pageerror");
|
|
368
571
|
actual = errors.length;
|
|
369
572
|
expected = 0;
|
|
370
573
|
passed = errors.length === 0;
|
|
@@ -372,8 +575,8 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
372
575
|
}
|
|
373
576
|
|
|
374
577
|
case "no_failed_requests_since": {
|
|
375
|
-
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline);
|
|
376
|
-
const failures = filtered.filter((e) => e.failed || (typeof e.status === "number" && e.status >= 400));
|
|
578
|
+
const filtered = getEntriesSince(allNetworkEntries, check.sinceActionId, actionTimeline!);
|
|
579
|
+
const failures = (filtered as typeof allNetworkEntries).filter((e) => e.failed || (typeof e.status === "number" && e.status >= 400));
|
|
377
580
|
actual = failures.length;
|
|
378
581
|
expected = 0;
|
|
379
582
|
passed = failures.length === 0;
|
|
@@ -417,11 +620,16 @@ export function evaluateAssertionChecks({ checks, state }) {
|
|
|
417
620
|
// Wait-condition validation
|
|
418
621
|
// ---------------------------------------------------------------------------
|
|
419
622
|
|
|
623
|
+
interface WaitConditionSpec {
|
|
624
|
+
needsValue: boolean;
|
|
625
|
+
valueLabel: string;
|
|
626
|
+
needsThreshold?: boolean;
|
|
627
|
+
}
|
|
628
|
+
|
|
420
629
|
/**
|
|
421
630
|
* All recognized wait conditions with their parameter requirements.
|
|
422
|
-
* Each entry: { needsValue: bool, valueLabel: string, needsThreshold?: bool }
|
|
423
631
|
*/
|
|
424
|
-
const WAIT_CONDITIONS = {
|
|
632
|
+
const WAIT_CONDITIONS: Record<string, WaitConditionSpec> = {
|
|
425
633
|
// Existing 5 conditions
|
|
426
634
|
selector_visible: { needsValue: true, valueLabel: "CSS selector" },
|
|
427
635
|
selector_hidden: { needsValue: true, valueLabel: "CSS selector" },
|
|
@@ -440,10 +648,8 @@ const WAIT_CONDITIONS = {
|
|
|
440
648
|
|
|
441
649
|
/**
|
|
442
650
|
* Validate parameters for a browser_wait_for condition.
|
|
443
|
-
* @param {{ condition: string, value?: string, threshold?: string }} params
|
|
444
|
-
* @returns {null | { error: string }} — null if valid, structured error otherwise
|
|
445
651
|
*/
|
|
446
|
-
export function validateWaitParams(params) {
|
|
652
|
+
export function validateWaitParams(params: { condition: string; value?: string; threshold?: string }): WaitValidationError | null {
|
|
447
653
|
const { condition, value, threshold } = params ?? {};
|
|
448
654
|
|
|
449
655
|
if (!condition) {
|
|
@@ -477,14 +683,8 @@ export function validateWaitParams(params) {
|
|
|
477
683
|
/**
|
|
478
684
|
* Generate a JS expression string for page.waitForFunction() that detects
|
|
479
685
|
* DOM stability by comparing snapshot hashes across polling intervals.
|
|
480
|
-
*
|
|
481
|
-
* The script stores a snapshot on a namespaced window key. When the snapshot
|
|
482
|
-
* matches the previous value, the region is considered stable.
|
|
483
|
-
*
|
|
484
|
-
* @param {string} selector — CSS selector for the target element
|
|
485
|
-
* @returns {string} — self-contained JS function body suitable for waitForFunction
|
|
486
686
|
*/
|
|
487
|
-
export function createRegionStableScript(selector) {
|
|
687
|
+
export function createRegionStableScript(selector: string): string {
|
|
488
688
|
// Create a stable key from the selector (simple hash to avoid special chars)
|
|
489
689
|
const safeKey = Array.from(selector).reduce((h, c) => ((h << 5) - h + c.charCodeAt(0)) | 0, 0) >>> 0;
|
|
490
690
|
const windowKey = `__pw_region_stable_${safeKey}`;
|
|
@@ -504,40 +704,20 @@ export function createRegionStableScript(selector) {
|
|
|
504
704
|
// Page Registry — pure-logic operations for multi-page/tab management
|
|
505
705
|
// ---------------------------------------------------------------------------
|
|
506
706
|
|
|
507
|
-
|
|
508
|
-
* Create a fresh page registry.
|
|
509
|
-
* @returns {{ pages: Array, activePageId: number | null, nextId: number }}
|
|
510
|
-
*/
|
|
511
|
-
export function createPageRegistry() {
|
|
707
|
+
export function createPageRegistry(): PageRegistry {
|
|
512
708
|
return { pages: [], activePageId: null, nextId: 1 };
|
|
513
709
|
}
|
|
514
710
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
* Add a page to the registry. Assigns an auto-incrementing ID.
|
|
521
|
-
* @param {ReturnType<typeof createPageRegistry>} registry
|
|
522
|
-
* @param {{ page: any, title?: string, url?: string, opener?: number | null }} info
|
|
523
|
-
* @returns {PageEntry}
|
|
524
|
-
*/
|
|
525
|
-
export function registryAddPage(registry, { page, title = "", url = "", opener = null }) {
|
|
526
|
-
const entry = { id: registry.nextId++, page, title, url, opener };
|
|
711
|
+
export function registryAddPage(
|
|
712
|
+
registry: PageRegistry,
|
|
713
|
+
{ page, title = "", url = "", opener = null }: { page: unknown; title?: string; url?: string; opener?: number | null },
|
|
714
|
+
): PageEntry {
|
|
715
|
+
const entry: PageEntry = { id: registry.nextId++, page, title, url, opener };
|
|
527
716
|
registry.pages.push(entry);
|
|
528
717
|
return entry;
|
|
529
718
|
}
|
|
530
719
|
|
|
531
|
-
|
|
532
|
-
* Remove a page from the registry by ID.
|
|
533
|
-
* If the removed page was active, falls back to the opener (if still present)
|
|
534
|
-
* or the last remaining page.
|
|
535
|
-
* Orphans any pages whose opener was the removed page (sets their opener to null).
|
|
536
|
-
* @param {ReturnType<typeof createPageRegistry>} registry
|
|
537
|
-
* @param {number} pageId
|
|
538
|
-
* @returns {{ removed: PageEntry, newActiveId: number | null }}
|
|
539
|
-
*/
|
|
540
|
-
export function registryRemovePage(registry, pageId) {
|
|
720
|
+
export function registryRemovePage(registry: PageRegistry, pageId: number): { removed: PageEntry; newActiveId: number | null } {
|
|
541
721
|
const idx = registry.pages.findIndex((p) => p.id === pageId);
|
|
542
722
|
if (idx === -1) {
|
|
543
723
|
const available = registry.pages.map((p) => p.id);
|
|
@@ -571,12 +751,7 @@ export function registryRemovePage(registry, pageId) {
|
|
|
571
751
|
return { removed, newActiveId };
|
|
572
752
|
}
|
|
573
753
|
|
|
574
|
-
|
|
575
|
-
* Set the active page by ID. Throws if the page is not in the registry.
|
|
576
|
-
* @param {ReturnType<typeof createPageRegistry>} registry
|
|
577
|
-
* @param {number} pageId
|
|
578
|
-
*/
|
|
579
|
-
export function registrySetActive(registry, pageId) {
|
|
754
|
+
export function registrySetActive(registry: PageRegistry, pageId: number): void {
|
|
580
755
|
const entry = registry.pages.find((p) => p.id === pageId);
|
|
581
756
|
if (!entry) {
|
|
582
757
|
const available = registry.pages.map((p) => p.id);
|
|
@@ -589,12 +764,7 @@ export function registrySetActive(registry, pageId) {
|
|
|
589
764
|
registry.activePageId = pageId;
|
|
590
765
|
}
|
|
591
766
|
|
|
592
|
-
|
|
593
|
-
* Get the active page entry. Throws if no active page or active page not found.
|
|
594
|
-
* @param {ReturnType<typeof createPageRegistry>} registry
|
|
595
|
-
* @returns {PageEntry}
|
|
596
|
-
*/
|
|
597
|
-
export function registryGetActive(registry) {
|
|
767
|
+
export function registryGetActive(registry: PageRegistry): PageEntry {
|
|
598
768
|
if (registry.activePageId === null) {
|
|
599
769
|
throw new Error(
|
|
600
770
|
`registryGetActive: no active page. ` +
|
|
@@ -613,22 +783,11 @@ export function registryGetActive(registry) {
|
|
|
613
783
|
return entry;
|
|
614
784
|
}
|
|
615
785
|
|
|
616
|
-
|
|
617
|
-
* Get a page entry by ID, or null if not found.
|
|
618
|
-
* @param {ReturnType<typeof createPageRegistry>} registry
|
|
619
|
-
* @param {number} pageId
|
|
620
|
-
* @returns {PageEntry | null}
|
|
621
|
-
*/
|
|
622
|
-
export function registryGetPage(registry, pageId) {
|
|
786
|
+
export function registryGetPage(registry: PageRegistry, pageId: number): PageEntry | null {
|
|
623
787
|
return registry.pages.find((p) => p.id === pageId) ?? null;
|
|
624
788
|
}
|
|
625
789
|
|
|
626
|
-
|
|
627
|
-
* List all pages (without the raw `page` reference).
|
|
628
|
-
* @param {ReturnType<typeof createPageRegistry>} registry
|
|
629
|
-
* @returns {Array<{ id: number, title: string, url: string, opener: number | null, isActive: boolean }>}
|
|
630
|
-
*/
|
|
631
|
-
export function registryListPages(registry) {
|
|
790
|
+
export function registryListPages(registry: PageRegistry): PageListEntry[] {
|
|
632
791
|
return registry.pages.map((entry) => ({
|
|
633
792
|
id: entry.id,
|
|
634
793
|
title: entry.title,
|
|
@@ -642,13 +801,8 @@ export function registryListPages(registry) {
|
|
|
642
801
|
// FIFO Bounded Log Pusher
|
|
643
802
|
// ---------------------------------------------------------------------------
|
|
644
803
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
* @param {number} maxSize — maximum number of entries to retain
|
|
648
|
-
* @returns {(array: Array, entry: any) => void}
|
|
649
|
-
*/
|
|
650
|
-
export function createBoundedLogPusher(maxSize) {
|
|
651
|
-
return function push(array, entry) {
|
|
804
|
+
export function createBoundedLogPusher(maxSize: number): (array: unknown[], entry: unknown) => void {
|
|
805
|
+
return function push(array: unknown[], entry: unknown): void {
|
|
652
806
|
array.push(entry);
|
|
653
807
|
if (array.length > maxSize) {
|
|
654
808
|
array.splice(0, array.length - maxSize);
|
|
@@ -656,10 +810,14 @@ export function createBoundedLogPusher(maxSize) {
|
|
|
656
810
|
};
|
|
657
811
|
}
|
|
658
812
|
|
|
659
|
-
export async function runBatchSteps({ steps, executeStep, stopOnFailure = true }
|
|
660
|
-
|
|
813
|
+
export async function runBatchSteps({ steps, executeStep, stopOnFailure = true }: {
|
|
814
|
+
steps: unknown[];
|
|
815
|
+
executeStep: (step: unknown, index: number) => Promise<{ ok: boolean; [key: string]: unknown }>;
|
|
816
|
+
stopOnFailure?: boolean;
|
|
817
|
+
}): Promise<BatchStepResult> {
|
|
818
|
+
const results: unknown[] = [];
|
|
661
819
|
for (let i = 0; i < steps.length; i += 1) {
|
|
662
|
-
const step = steps[i];
|
|
820
|
+
const step = steps[i] as { action: string };
|
|
663
821
|
const result = await executeStep(step, i);
|
|
664
822
|
results.push(result);
|
|
665
823
|
if (result.ok === false && stopOnFailure) {
|
|
@@ -685,15 +843,7 @@ export async function runBatchSteps({ steps, executeStep, stopOnFailure = true }
|
|
|
685
843
|
// Snapshot Modes — semantic element filtering for browser_snapshot_refs
|
|
686
844
|
// ---------------------------------------------------------------------------
|
|
687
845
|
|
|
688
|
-
|
|
689
|
-
* Pre-defined snapshot modes that filter elements by semantic category.
|
|
690
|
-
* Each mode config defines which elements should be captured.
|
|
691
|
-
*
|
|
692
|
-
* Shape: { tags: string[], roles: string[], selectors: string[],
|
|
693
|
-
* ariaAttributes: string[], useInteractiveFilter: boolean,
|
|
694
|
-
* visibleOnly?: boolean, containerExpand?: boolean }
|
|
695
|
-
*/
|
|
696
|
-
export const SNAPSHOT_MODES = {
|
|
846
|
+
export const SNAPSHOT_MODES: Record<string, SnapshotModeConfig> = {
|
|
697
847
|
interactive: {
|
|
698
848
|
tags: [],
|
|
699
849
|
roles: [],
|
|
@@ -748,12 +898,7 @@ export const SNAPSHOT_MODES = {
|
|
|
748
898
|
},
|
|
749
899
|
};
|
|
750
900
|
|
|
751
|
-
|
|
752
|
-
* Get the snapshot mode config by name.
|
|
753
|
-
* @param {string} mode — mode name (e.g. "form", "dialog", "interactive")
|
|
754
|
-
* @returns {{ tags: string[], roles: string[], selectors: string[], ariaAttributes: string[], useInteractiveFilter: boolean, visibleOnly?: boolean, containerExpand?: boolean } | null}
|
|
755
|
-
*/
|
|
756
|
-
export function getSnapshotModeConfig(mode) {
|
|
901
|
+
export function getSnapshotModeConfig(mode: string): SnapshotModeConfig | null {
|
|
757
902
|
return SNAPSHOT_MODES[mode] ?? null;
|
|
758
903
|
}
|
|
759
904
|
|
|
@@ -761,13 +906,7 @@ export function getSnapshotModeConfig(mode) {
|
|
|
761
906
|
// Fingerprint functions — structural identity for ref resolution
|
|
762
907
|
// ---------------------------------------------------------------------------
|
|
763
908
|
|
|
764
|
-
|
|
765
|
-
* Compute a content hash from visible text using djb2.
|
|
766
|
-
* Caller is expected to pre-truncate to ~200 chars and normalize whitespace.
|
|
767
|
-
* @param {string} text — visible text content
|
|
768
|
-
* @returns {string} — hex string hash, or "0" for empty input
|
|
769
|
-
*/
|
|
770
|
-
export function computeContentHash(text) {
|
|
909
|
+
export function computeContentHash(text: string): string {
|
|
771
910
|
if (!text) return "0";
|
|
772
911
|
let h = 5381;
|
|
773
912
|
for (let i = 0; i < text.length; i++) {
|
|
@@ -776,15 +915,7 @@ export function computeContentHash(text) {
|
|
|
776
915
|
return (h >>> 0).toString(16);
|
|
777
916
|
}
|
|
778
917
|
|
|
779
|
-
|
|
780
|
-
* Compute a structural signature from tag, role, and immediate child tag names.
|
|
781
|
-
* Uses djb2 hash on the concatenated string `tag|role|child1,child2,...`.
|
|
782
|
-
* @param {string} tag — element tag name (lowercase)
|
|
783
|
-
* @param {string} role — ARIA role or empty string
|
|
784
|
-
* @param {string[]} childTags — array of immediate child tag names (lowercase)
|
|
785
|
-
* @returns {string} — hex string hash
|
|
786
|
-
*/
|
|
787
|
-
export function computeStructuralSignature(tag, role, childTags) {
|
|
918
|
+
export function computeStructuralSignature(tag: string, role: string, childTags: string[]): string {
|
|
788
919
|
const input = `${tag}|${role}|${childTags.join(",")}`;
|
|
789
920
|
let h = 5381;
|
|
790
921
|
for (let i = 0; i < input.length; i++) {
|
|
@@ -793,14 +924,10 @@ export function computeStructuralSignature(tag, role, childTags) {
|
|
|
793
924
|
return (h >>> 0).toString(16);
|
|
794
925
|
}
|
|
795
926
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
* @param {{ contentHash?: string, structuralSignature?: string }} candidate
|
|
801
|
-
* @returns {boolean}
|
|
802
|
-
*/
|
|
803
|
-
export function matchFingerprint(stored, candidate) {
|
|
927
|
+
export function matchFingerprint(
|
|
928
|
+
stored: { contentHash?: string; structuralSignature?: string },
|
|
929
|
+
candidate: { contentHash?: string; structuralSignature?: string },
|
|
930
|
+
): boolean {
|
|
804
931
|
if (!stored || !candidate) return false;
|
|
805
932
|
if (!stored.contentHash || !stored.structuralSignature) return false;
|
|
806
933
|
if (!candidate.contentHash || !candidate.structuralSignature) return false;
|
|
@@ -808,30 +935,34 @@ export function matchFingerprint(stored, candidate) {
|
|
|
808
935
|
stored.structuralSignature === candidate.structuralSignature;
|
|
809
936
|
}
|
|
810
937
|
|
|
811
|
-
|
|
938
|
+
// ---------------------------------------------------------------------------
|
|
939
|
+
// Timeline Formatting
|
|
940
|
+
// ---------------------------------------------------------------------------
|
|
941
|
+
|
|
942
|
+
function formatDurationMs(entry: { startedAt?: number; finishedAt?: number | null }): number | null {
|
|
812
943
|
const startedAt = typeof entry?.startedAt === "number" ? entry.startedAt : null;
|
|
813
944
|
const finishedAt = typeof entry?.finishedAt === "number" ? entry.finishedAt : null;
|
|
814
945
|
if (startedAt == null || finishedAt == null || finishedAt < startedAt) return null;
|
|
815
946
|
return finishedAt - startedAt;
|
|
816
947
|
}
|
|
817
948
|
|
|
818
|
-
function summarizeActionStatus(status) {
|
|
949
|
+
function summarizeActionStatus(status: string | undefined): string {
|
|
819
950
|
if (status === "error") return "error";
|
|
820
951
|
if (status === "running") return "running";
|
|
821
952
|
return "success";
|
|
822
953
|
}
|
|
823
954
|
|
|
824
|
-
function looksBoundedWarning(value) {
|
|
955
|
+
function looksBoundedWarning(value: unknown): boolean {
|
|
825
956
|
return /bounded .*history/i.test(String(value ?? ""));
|
|
826
957
|
}
|
|
827
958
|
|
|
828
|
-
function uniqueStrings(values) {
|
|
829
|
-
return [...new Set(values.filter(Boolean))];
|
|
959
|
+
function uniqueStrings(values: (string | undefined)[]): string[] {
|
|
960
|
+
return [...new Set(values.filter(Boolean))] as string[];
|
|
830
961
|
}
|
|
831
962
|
|
|
832
|
-
export function formatTimelineEntries(entries = [], options = {}) {
|
|
833
|
-
const retained = options.retained ?? entries.length;
|
|
834
|
-
const totalRecorded = options.totalRecorded ?? retained;
|
|
963
|
+
export function formatTimelineEntries(entries: ActionEntry[] = [], options: Record<string, unknown> = {}): FormattedTimeline {
|
|
964
|
+
const retained = (options.retained as number) ?? entries.length;
|
|
965
|
+
const totalRecorded = (options.totalRecorded as number) ?? retained;
|
|
835
966
|
const bounded = totalRecorded > retained;
|
|
836
967
|
|
|
837
968
|
if (!entries.length) {
|
|
@@ -847,7 +978,7 @@ export function formatTimelineEntries(entries = [], options = {}) {
|
|
|
847
978
|
const formattedEntries = entries.map((entry) => {
|
|
848
979
|
const status = summarizeActionStatus(entry.status);
|
|
849
980
|
const durationMs = formatDurationMs(entry);
|
|
850
|
-
const parts = [
|
|
981
|
+
const parts: string[] = [
|
|
851
982
|
`#${entry.id ?? "?"}`,
|
|
852
983
|
entry.tool ?? "unknown_tool",
|
|
853
984
|
status,
|
|
@@ -884,12 +1015,16 @@ export function formatTimelineEntries(entries = [], options = {}) {
|
|
|
884
1015
|
};
|
|
885
1016
|
}
|
|
886
1017
|
|
|
887
|
-
|
|
1018
|
+
// ---------------------------------------------------------------------------
|
|
1019
|
+
// Failure Hypothesis
|
|
1020
|
+
// ---------------------------------------------------------------------------
|
|
1021
|
+
|
|
1022
|
+
export function buildFailureHypothesis(session: Record<string, any> = {}): FailureHypothesis {
|
|
888
1023
|
const timelineEntries = session.actionTimeline?.entries ?? [];
|
|
889
1024
|
const consoleEntries = session.consoleEntries ?? [];
|
|
890
1025
|
const networkEntries = session.networkEntries ?? [];
|
|
891
1026
|
const dialogEntries = session.dialogEntries ?? [];
|
|
892
|
-
const signals = [];
|
|
1027
|
+
const signals: Array<{ category: string; source: string; detail: string }> = [];
|
|
893
1028
|
|
|
894
1029
|
for (const entry of timelineEntries) {
|
|
895
1030
|
if (entry?.status !== "error") continue;
|
|
@@ -920,7 +1055,7 @@ export function buildFailureHypothesis(session = {}) {
|
|
|
920
1055
|
if (entry?.type !== "error" && entry?.type !== "pageerror") continue;
|
|
921
1056
|
signals.push({
|
|
922
1057
|
category: "console",
|
|
923
|
-
source: entry.type
|
|
1058
|
+
source: entry.type!,
|
|
924
1059
|
detail: entry.text || "Console error recorded",
|
|
925
1060
|
});
|
|
926
1061
|
}
|
|
@@ -957,18 +1092,22 @@ export function buildFailureHypothesis(session = {}) {
|
|
|
957
1092
|
};
|
|
958
1093
|
}
|
|
959
1094
|
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
const
|
|
966
|
-
const
|
|
967
|
-
const
|
|
968
|
-
const
|
|
1095
|
+
// ---------------------------------------------------------------------------
|
|
1096
|
+
// Session Summary
|
|
1097
|
+
// ---------------------------------------------------------------------------
|
|
1098
|
+
|
|
1099
|
+
export function summarizeBrowserSession(session: Record<string, any> = {}): SessionSummary {
|
|
1100
|
+
const actionTimeline = session.actionTimeline ?? { limit: 0, entries: [] as ActionEntry[] };
|
|
1101
|
+
const actionEntries: ActionEntry[] = actionTimeline.entries ?? [];
|
|
1102
|
+
const retainedActionCount: number = session.retainedActionCount ?? actionEntries.length;
|
|
1103
|
+
const totalActionCount: number = session.totalActionCount ?? retainedActionCount;
|
|
1104
|
+
const pages: Array<Record<string, any>> = session.pages ?? [];
|
|
1105
|
+
const consoleEntries: Array<Record<string, any>> = session.consoleEntries ?? [];
|
|
1106
|
+
const networkEntries: Array<Record<string, any>> = session.networkEntries ?? [];
|
|
1107
|
+
const dialogEntries: Array<Record<string, any>> = session.dialogEntries ?? [];
|
|
969
1108
|
|
|
970
1109
|
const actionStatusCounts = actionEntries.reduce(
|
|
971
|
-
(acc, entry) => {
|
|
1110
|
+
(acc: Record<string, number>, entry: ActionEntry) => {
|
|
972
1111
|
const status = summarizeActionStatus(entry.status);
|
|
973
1112
|
acc[status] = (acc[status] ?? 0) + 1;
|
|
974
1113
|
return acc;
|
|
@@ -976,13 +1115,13 @@ export function summarizeBrowserSession(session = {}) {
|
|
|
976
1115
|
{ success: 0, error: 0, running: 0 },
|
|
977
1116
|
);
|
|
978
1117
|
|
|
979
|
-
const waitEntries = actionEntries.filter((entry) => entry.tool === "browser_wait_for");
|
|
980
|
-
const assertEntries = actionEntries.filter((entry) => entry.tool === "browser_assert");
|
|
981
|
-
const consoleErrors = consoleEntries.filter((entry) => entry.type === "error" || entry.type === "pageerror");
|
|
982
|
-
const failedRequests = networkEntries.filter((entry) => entry.failed || (typeof entry.status === "number" && entry.status >= 400));
|
|
983
|
-
const activePage = pages.find((page) => page.isActive) ?? pages[0] ?? null;
|
|
1118
|
+
const waitEntries = actionEntries.filter((entry: ActionEntry) => entry.tool === "browser_wait_for");
|
|
1119
|
+
const assertEntries = actionEntries.filter((entry: ActionEntry) => entry.tool === "browser_assert");
|
|
1120
|
+
const consoleErrors = consoleEntries.filter((entry: Record<string, any>) => entry.type === "error" || entry.type === "pageerror");
|
|
1121
|
+
const failedRequests = networkEntries.filter((entry: Record<string, any>) => entry.failed || (typeof entry.status === "number" && entry.status >= 400));
|
|
1122
|
+
const activePage = pages.find((page: Record<string, any>) => page.isActive) ?? pages[0] ?? null;
|
|
984
1123
|
|
|
985
|
-
const caveats = [];
|
|
1124
|
+
const caveats: string[] = [];
|
|
986
1125
|
if (totalActionCount > retainedActionCount) {
|
|
987
1126
|
caveats.push(`Showing ${retainedActionCount} of ${totalActionCount} recorded actions; older actions were discarded due to bounded history.`);
|
|
988
1127
|
}
|