pi-agent-browser-native 0.9.3 → 0.9.4
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/CHANGELOG.md +77 -5
- package/README.md +103 -81
- package/dist/extensions/agent-browser/index.js +43057 -2031
- package/dist/extensions/agent-browser/lib/argv-descriptor.js +49 -26
- package/dist/extensions/agent-browser/lib/argv-grammar.js +82 -93
- package/dist/extensions/agent-browser/lib/bash-guard.js +129 -126
- package/dist/extensions/agent-browser/lib/batch-lifecycle.js +112 -51
- package/dist/extensions/agent-browser/lib/browser-execution-claim-codec.js +61 -0
- package/dist/extensions/agent-browser/lib/browser-execution-claim-storage.js +232 -0
- package/dist/extensions/agent-browser/lib/browser-execution-claims.js +202 -0
- package/dist/extensions/agent-browser/lib/browser-execution-identity.js +77 -0
- package/dist/extensions/agent-browser/lib/browser-journal-branch.js +98 -0
- package/dist/extensions/agent-browser/lib/browser-journal-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/browser-journal-projection.js +221 -0
- package/dist/extensions/agent-browser/lib/browser-journal-reader.js +89 -0
- package/dist/extensions/agent-browser/lib/browser-journal-replay.js +246 -0
- package/dist/extensions/agent-browser/lib/browser-journal.js +103 -394
- package/dist/extensions/agent-browser/lib/browser-legacy-pages.js +220 -0
- package/dist/extensions/agent-browser/lib/browser-legacy-projection.js +282 -0
- package/dist/extensions/agent-browser/lib/browser-legacy-types.js +1 -0
- package/dist/extensions/agent-browser/lib/browser-session-conversion-stream.js +217 -0
- package/dist/extensions/agent-browser/lib/browser-session-conversion.js +80 -335
- package/dist/extensions/agent-browser/lib/browser-transcript-contracts.js +35 -0
- package/dist/extensions/agent-browser/lib/browser-transcript-validation.js +166 -0
- package/dist/extensions/agent-browser/lib/browser-transcript.js +137 -82
- package/dist/extensions/agent-browser/lib/browser-value-parsing.js +15 -0
- package/dist/extensions/agent-browser/lib/command-capabilities.js +340 -0
- package/dist/extensions/agent-browser/lib/command-policy.js +107 -88
- package/dist/extensions/agent-browser/lib/command-taxonomy.js +49 -322
- package/dist/extensions/agent-browser/lib/config-policy.js +138 -343
- package/dist/extensions/agent-browser/lib/config-providers.js +71 -0
- package/dist/extensions/agent-browser/lib/config-validation.js +218 -0
- package/dist/extensions/agent-browser/lib/config.js +19 -7
- package/dist/extensions/agent-browser/lib/electron/cdp.js +15 -7
- package/dist/extensions/agent-browser/lib/electron/cleanup.js +134 -55
- package/dist/extensions/agent-browser/lib/electron/discovery-darwin.js +109 -0
- package/dist/extensions/agent-browser/lib/electron/discovery-desktop.js +136 -0
- package/dist/extensions/agent-browser/lib/electron/discovery-evidence.js +89 -0
- package/dist/extensions/agent-browser/lib/electron/discovery-linux.js +93 -0
- package/dist/extensions/agent-browser/lib/electron/discovery-packages.js +162 -0
- package/dist/extensions/agent-browser/lib/electron/discovery-types.js +2 -0
- package/dist/extensions/agent-browser/lib/electron/discovery.js +140 -549
- package/dist/extensions/agent-browser/lib/electron/launch-monitor.js +102 -0
- package/dist/extensions/agent-browser/lib/electron/launch-process.js +209 -0
- package/dist/extensions/agent-browser/lib/electron/launch-types.js +2 -0
- package/dist/extensions/agent-browser/lib/electron/launch.js +249 -354
- package/dist/extensions/agent-browser/lib/executable-path.js +21 -12
- package/dist/extensions/agent-browser/lib/execution-cwd.js +35 -18
- package/dist/extensions/agent-browser/lib/input-modes/electron.js +162 -121
- package/dist/extensions/agent-browser/lib/input-modes/job.js +116 -313
- package/dist/extensions/agent-browser/lib/input-modes/lookup-network-evidence.js +104 -0
- package/dist/extensions/agent-browser/lib/input-modes/lookup-plan.js +132 -0
- package/dist/extensions/agent-browser/lib/input-modes/lookup-redaction.js +57 -0
- package/dist/extensions/agent-browser/lib/input-modes/lookup-source-evidence.js +151 -0
- package/dist/extensions/agent-browser/lib/input-modes/lookup-workspace.js +142 -0
- package/dist/extensions/agent-browser/lib/input-modes/lookups.js +57 -412
- package/dist/extensions/agent-browser/lib/input-modes/params.js +63 -17
- package/dist/extensions/agent-browser/lib/input-modes/qa-analysis.js +268 -0
- package/dist/extensions/agent-browser/lib/input-modes/qa-presentation.js +117 -0
- package/dist/extensions/agent-browser/lib/input-modes/script-child.js +396 -0
- package/dist/extensions/agent-browser/lib/input-modes/script-protocol.js +86 -0
- package/dist/extensions/agent-browser/lib/input-modes/script-types.js +1 -0
- package/dist/extensions/agent-browser/lib/input-modes/script-validation.js +60 -0
- package/dist/extensions/agent-browser/lib/input-modes/script.js +60 -409
- package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +218 -128
- package/dist/extensions/agent-browser/lib/input-modes/shared.js +15 -4
- package/dist/extensions/agent-browser/lib/input-modes/types.js +56 -7
- package/dist/extensions/agent-browser/lib/json-schema.js +22 -10
- package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +17 -5
- package/dist/extensions/agent-browser/lib/managed-session-policy-lock.js +92 -425
- package/dist/extensions/agent-browser/lib/managed-session-posix-storage.js +58 -0
- package/dist/extensions/agent-browser/lib/managed-session-project-identity.js +244 -0
- package/dist/extensions/agent-browser/lib/managed-session-restore-context.js +84 -0
- package/dist/extensions/agent-browser/lib/managed-session-restore-policy.js +119 -0
- package/dist/extensions/agent-browser/lib/managed-session-restore-state.js +83 -0
- package/dist/extensions/agent-browser/lib/managed-session-restore.js +168 -300
- package/dist/extensions/agent-browser/lib/managed-session-snapshot-records.js +277 -0
- package/dist/extensions/agent-browser/lib/managed-session-snapshots.js +128 -305
- package/dist/extensions/agent-browser/lib/managed-session-storage.js +56 -253
- package/dist/extensions/agent-browser/lib/native-confirmation.js +140 -0
- package/dist/extensions/agent-browser/lib/native-output.js +43 -9
- package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +106 -59
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-merge.js +14 -6
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +109 -57
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/browser-observation-result.js +82 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +164 -60
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostic-values.js +31 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +152 -781
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-observation.js +202 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-text-diagnostics.js +109 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/fill-diagnostics.js +119 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-action-recovery.js +147 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-actions.js +144 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-content.js +123 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-details.js +156 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-electron.js +179 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-evidence.js +39 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-missing-binary.js +89 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-recovery.js +97 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-redaction.js +106 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-timeout.js +110 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +41 -538
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +199 -154
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/interaction-diagnostics.js +290 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-close.js +167 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-inspection.js +108 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +127 -205
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/native-helper-observation.js +65 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/observation-types.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/overlay-diagnostics.js +120 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +113 -30
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +109 -28
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter-data.js +150 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +138 -253
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-rendered-text.js +147 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +59 -24
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-artifacts.js +159 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-command.js +131 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-daemon.js +93 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-failure.js +42 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-guards.js +242 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-input.js +75 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-observations.js +92 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-selection.js +254 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-state.js +121 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-refs.js +130 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-resources.js +114 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-semantic.js +121 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-session-plan.js +222 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-timeouts.js +68 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +176 -1123
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-analysis.js +191 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-confirmation.js +152 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-diagnostics.js +182 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-electron.js +150 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase.js +115 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle.js +256 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed.js +256 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase.js +93 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native.js +113 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation.js +316 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-ownership.js +28 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase.js +142 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation.js +333 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase.js +71 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication.js +201 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-receipts.js +183 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-refs.js +200 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-tabs.js +142 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +18 -968
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.js +23 -13
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-receipt-reconciliation.js +198 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-presentation.js +154 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery.js +68 -151
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-capture.js +14 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-observation.js +169 -46
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-commands.js +130 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-electron.js +210 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-observations.js +61 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-outcomes.js +187 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-refs.js +171 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-tabs.js +228 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +77 -765
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/text-visibility-diagnostics.js +182 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-diagnostics.js +256 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-progress.js +108 -0
- package/dist/extensions/agent-browser/lib/orchestration/code-artifact-observation.js +39 -0
- package/dist/extensions/agent-browser/lib/orchestration/code-image-observation.js +119 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/branch.js +92 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup-result.js +58 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup.js +78 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/discovery.js +106 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +48 -821
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/policy.js +86 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-collection.js +69 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-data.js +167 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-presentation.js +164 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe.js +161 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/status.js +165 -0
- package/dist/extensions/agent-browser/lib/orchestration/execution-queue.js +21 -9
- package/dist/extensions/agent-browser/lib/orchestration/extension-artifact-preflight.js +211 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-artifacts.js +23 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-attachment-replay.js +99 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-branch-restore.js +275 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-code.js +280 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-command-admission.js +303 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-command-output.js +36 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-command-result.js +335 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-command-run.js +227 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-command-state.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-electron-ownership.js +204 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-execution-locks.js +139 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-execution-queue.js +24 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-host-coordination.js +98 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-host-run.js +295 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-intent-replay.js +41 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-invocation.js +7 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-lifecycle.js +102 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-managed-ownership.js +133 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-observation.js +120 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-prompt.js +180 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-recording.js +290 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-resource-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-resource-replay.js +269 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-result-state.js +113 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-runtime.js +146 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-script-leases.js +58 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-tool-boundary.js +62 -0
- package/dist/extensions/agent-browser/lib/orchestration/extension-version-check.js +54 -0
- package/dist/extensions/agent-browser/lib/orchestration/input-plan-types.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +261 -185
- package/dist/extensions/agent-browser/lib/orchestration/input-redaction.js +62 -0
- package/dist/extensions/agent-browser/lib/orchestration/native-config.js +144 -0
- package/dist/extensions/agent-browser/lib/orchestration/native-root-launch.js +77 -0
- package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +210 -157
- package/dist/extensions/agent-browser/lib/orchestration/operation-paths.js +124 -58
- package/dist/extensions/agent-browser/lib/orchestration/output-file.js +197 -99
- package/dist/extensions/agent-browser/lib/orchestration/script-mode.js +199 -96
- package/dist/extensions/agent-browser/lib/owned-managed-session-context.js +55 -0
- package/dist/extensions/agent-browser/lib/page-target-batch.js +118 -0
- package/dist/extensions/agent-browser/lib/page-target-guards.js +50 -0
- package/dist/extensions/agent-browser/lib/page-target-navigation.js +104 -0
- package/dist/extensions/agent-browser/lib/page-target-validation.js +55 -246
- package/dist/extensions/agent-browser/lib/parsing.js +13 -4
- package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +133 -68
- package/dist/extensions/agent-browser/lib/playbook.js +16 -12
- package/dist/extensions/agent-browser/lib/process-child.js +284 -0
- package/dist/extensions/agent-browser/lib/process-environment.js +13 -6
- package/dist/extensions/agent-browser/lib/process-errors.js +23 -0
- package/dist/extensions/agent-browser/lib/process-identity.js +47 -15
- package/dist/extensions/agent-browser/lib/process-socket-storage.js +256 -0
- package/dist/extensions/agent-browser/lib/process-stdout.js +74 -0
- package/dist/extensions/agent-browser/lib/process.js +145 -536
- package/dist/extensions/agent-browser/lib/prompt-artifacts.js +287 -0
- package/dist/extensions/agent-browser/lib/prompt-policy.js +15 -194
- package/dist/extensions/agent-browser/lib/read-command.js +41 -0
- package/dist/extensions/agent-browser/lib/read-confirmation.js +131 -68
- package/dist/extensions/agent-browser/lib/recording-reservations.js +118 -45
- package/dist/extensions/agent-browser/lib/redaction-fields.js +75 -0
- package/dist/extensions/agent-browser/lib/redaction-json.js +149 -0
- package/dist/extensions/agent-browser/lib/redaction-url.js +88 -0
- package/dist/extensions/agent-browser/lib/results/action-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/results/action-recommendations.js +28 -271
- package/dist/extensions/agent-browser/lib/results/artifact-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/results/artifact-manifest-validation.js +133 -0
- package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +96 -94
- package/dist/extensions/agent-browser/lib/results/artifact-recommendations.js +73 -0
- package/dist/extensions/agent-browser/lib/results/categories.js +111 -54
- package/dist/extensions/agent-browser/lib/results/confirmation.js +29 -13
- package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +62 -27
- package/dist/extensions/agent-browser/lib/results/electron-recommendations.js +83 -0
- package/dist/extensions/agent-browser/lib/results/envelope-decoding.js +48 -0
- package/dist/extensions/agent-browser/lib/results/envelope.js +90 -67
- package/dist/extensions/agent-browser/lib/results/evidence-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/results/failure-recommendations.js +180 -0
- package/dist/extensions/agent-browser/lib/results/network-routes.js +86 -45
- package/dist/extensions/agent-browser/lib/results/network.js +35 -12
- package/dist/extensions/agent-browser/lib/results/next-actions.js +49 -19
- package/dist/extensions/agent-browser/lib/results/presentation/artifact-files.js +320 -0
- package/dist/extensions/agent-browser/lib/results/presentation/artifact-format.js +138 -0
- package/dist/extensions/agent-browser/lib/results/presentation/artifact-images.js +113 -0
- package/dist/extensions/agent-browser/lib/results/presentation/artifact-verification.js +145 -0
- package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +99 -555
- package/dist/extensions/agent-browser/lib/results/presentation/batch-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/results/presentation/batch-recording.js +118 -0
- package/dist/extensions/agent-browser/lib/results/presentation/batch-redaction.js +68 -0
- package/dist/extensions/agent-browser/lib/results/presentation/batch-rendering.js +135 -0
- package/dist/extensions/agent-browser/lib/results/presentation/batch-step.js +227 -0
- package/dist/extensions/agent-browser/lib/results/presentation/batch-summary.js +91 -0
- package/dist/extensions/agent-browser/lib/results/presentation/batch.js +91 -460
- package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +9 -5
- package/dist/extensions/agent-browser/lib/results/presentation/command-presenters.js +216 -0
- package/dist/extensions/agent-browser/lib/results/presentation/common.js +26 -9
- package/dist/extensions/agent-browser/lib/results/presentation/content.js +86 -29
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-a11y.js +67 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-health.js +79 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-identity.js +199 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-logs.js +75 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network-actions.js +216 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network.js +124 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-redaction.js +64 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-storage.js +209 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-stream.js +69 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-summary.js +222 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +103 -1052
- package/dist/extensions/agent-browser/lib/results/presentation/early-result.js +70 -0
- package/dist/extensions/agent-browser/lib/results/presentation/errors.js +130 -60
- package/dist/extensions/agent-browser/lib/results/presentation/input-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +60 -145
- package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +147 -88
- package/dist/extensions/agent-browser/lib/results/presentation/notices.js +75 -0
- package/dist/extensions/agent-browser/lib/results/presentation/observation-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/results/presentation/observation-rendering.js +127 -0
- package/dist/extensions/agent-browser/lib/results/presentation/outcomes.js +120 -0
- package/dist/extensions/agent-browser/lib/results/presentation/output-completion.js +77 -0
- package/dist/extensions/agent-browser/lib/results/presentation/output-spill.js +51 -0
- package/dist/extensions/agent-browser/lib/results/presentation/registry.js +116 -240
- package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +35 -21
- package/dist/extensions/agent-browser/lib/results/presentation/skills.js +104 -73
- package/dist/extensions/agent-browser/lib/results/presentation/source.js +109 -0
- package/dist/extensions/agent-browser/lib/results/presentation.js +17 -261
- package/dist/extensions/agent-browser/lib/results/recommendation-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/results/recording.js +52 -14
- package/dist/extensions/agent-browser/lib/results/recovery-actions.js +14 -5
- package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +30 -22
- package/dist/extensions/agent-browser/lib/results/selector-recovery-target.js +83 -0
- package/dist/extensions/agent-browser/lib/results/selector-recovery.js +119 -119
- package/dist/extensions/agent-browser/lib/results/snapshot-compact.js +266 -0
- package/dist/extensions/agent-browser/lib/results/snapshot-content.js +32 -0
- package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +104 -71
- package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +31 -11
- package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +125 -66
- package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +26 -7
- package/dist/extensions/agent-browser/lib/results/snapshot.js +28 -248
- package/dist/extensions/agent-browser/lib/results/text.js +16 -5
- package/dist/extensions/agent-browser/lib/runtime-args-validation.js +133 -0
- package/dist/extensions/agent-browser/lib/runtime-compatibility.js +81 -0
- package/dist/extensions/agent-browser/lib/runtime-contracts.js +1 -0
- package/dist/extensions/agent-browser/lib/runtime-redaction.js +118 -0
- package/dist/extensions/agent-browser/lib/runtime-replay-events.js +144 -0
- package/dist/extensions/agent-browser/lib/runtime-session-identity.js +76 -0
- package/dist/extensions/agent-browser/lib/runtime-session-plan.js +114 -0
- package/dist/extensions/agent-browser/lib/runtime-session-replay.js +123 -0
- package/dist/extensions/agent-browser/lib/runtime-tab-correction.js +65 -0
- package/dist/extensions/agent-browser/lib/runtime-timeouts.js +28 -0
- package/dist/extensions/agent-browser/lib/runtime.js +137 -1041
- package/dist/extensions/agent-browser/lib/session-identity.js +51 -0
- package/dist/extensions/agent-browser/lib/session-page-observation.js +357 -0
- package/dist/extensions/agent-browser/lib/session-page-state.js +178 -333
- package/dist/extensions/agent-browser/lib/session-page-types.js +1 -0
- package/dist/extensions/agent-browser/lib/temp-artifact-budget.js +78 -0
- package/dist/extensions/agent-browser/lib/temp-mutation-queue.js +7 -0
- package/dist/extensions/agent-browser/lib/temp-root-ownership.js +234 -0
- package/dist/extensions/agent-browser/lib/temp-root.js +207 -0
- package/dist/extensions/agent-browser/lib/temp.js +33 -446
- package/dist/extensions/agent-browser/lib/tool-surface.js +94 -24
- package/dist/extensions/agent-browser/lib/upstream-version.js +3 -2
- package/dist/extensions/agent-browser/lib/web-search-providers.js +229 -0
- package/dist/extensions/agent-browser/lib/web-search-request.js +108 -0
- package/dist/extensions/agent-browser/lib/web-search-results.js +281 -0
- package/dist/extensions/agent-browser/lib/web-search-schema.js +82 -0
- package/dist/extensions/agent-browser/lib/web-search.js +109 -617
- package/dist/extensions/agent-browser/lib/webmcp-observation.js +13 -6
- package/dist/extensions/agent-browser/lib/windows-stock-launcher.js +63 -37
- package/dist/extensions/agent-browser/script-worker.js +80 -43
- package/dist/scripts/agent-browser-target.mjs +4 -2
- package/docs/ARCHITECTURE.md +17 -5
- package/docs/CODE_QUALITY.md +242 -0
- package/docs/COMMAND_REFERENCE.md +251 -220
- package/docs/ELECTRON.md +53 -44
- package/docs/RELEASE.md +18 -15
- package/docs/REQUIREMENTS.md +1 -0
- package/docs/SUPPORT_MATRIX.md +76 -75
- package/docs/TOOL_CONTRACT.md +145 -116
- package/docs/platform-smoke.md +5 -5
- package/package.json +143 -120
- package/scripts/agent-browser-capability-baseline.mjs +361 -957
- package/scripts/agent-browser-target.mjs +6 -2
- package/scripts/build.mjs +37 -8
- package/scripts/capability-core-commands.mjs +193 -0
- package/scripts/capability-options.mjs +283 -0
- package/scripts/capability-samples.mjs +133 -0
- package/scripts/capability-section.mjs +11 -0
- package/scripts/config.mjs +213 -114
- package/scripts/convert-browser-session.mjs +30 -9
- package/scripts/doctor-sources.mjs +195 -0
- package/scripts/doctor.mjs +92 -247
- package/scripts/platform-smoke/artifacts.mjs +38 -11
- package/scripts/platform-smoke/commands.mjs +104 -0
- package/scripts/platform-smoke/crabbox-runner.mjs +167 -80
- package/scripts/platform-smoke/doctor-support.mjs +157 -0
- package/scripts/platform-smoke/doctor-windows.mjs +230 -0
- package/scripts/platform-smoke/doctor.mjs +212 -320
- package/scripts/platform-smoke/lease-evidence.mjs +134 -0
- package/scripts/platform-smoke/suite-checks.mjs +98 -0
- package/scripts/platform-smoke/suite-evidence.mjs +281 -0
- package/scripts/platform-smoke/targets.mjs +158 -472
- package/scripts/platform-smoke.mjs +55 -40
- package/scripts/prepare.mjs +16 -7
|
@@ -1,1073 +1,124 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"api-key",
|
|
24
|
-
"api_key",
|
|
25
|
-
"authentication",
|
|
26
|
-
"authorization",
|
|
27
|
-
"bearer",
|
|
28
|
-
"credential",
|
|
29
|
-
"credentials",
|
|
30
|
-
"jwt",
|
|
31
|
-
"passwd",
|
|
32
|
-
"password",
|
|
33
|
-
"reset",
|
|
34
|
-
"secret",
|
|
35
|
-
"session",
|
|
36
|
-
"token",
|
|
37
|
-
];
|
|
38
|
-
const NETWORK_FILTER_OPAQUE_SEGMENT_PATTERN = /^(?:[A-Fa-f0-9]{16,}|(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9_-]{16,})$/;
|
|
39
|
-
const NETWORK_PREVIEW_FIELD_CANDIDATES = {
|
|
40
|
-
request: ["postData"],
|
|
41
|
-
response: ["responseBody"],
|
|
42
|
-
error: ["error", "failureText", "errorText"],
|
|
43
|
-
};
|
|
44
|
-
const AUTH_SHOW_SAFE_FIELDS = ["name", "profile", "url", "username", "createdAt", "updatedAt"];
|
|
45
|
-
export function getTabSummary(data) {
|
|
46
|
-
const tabs = Array.isArray(data.tabs) ? data.tabs : undefined;
|
|
47
|
-
if (!tabs)
|
|
48
|
-
return undefined;
|
|
49
|
-
const lines = tabs.map((tab, index) => {
|
|
50
|
-
if (!isRecord(tab))
|
|
51
|
-
return `${index}: <invalid tab>`;
|
|
52
|
-
const marker = tab.active === true ? "*" : "-";
|
|
53
|
-
const title = typeof tab.title === "string" ? tab.title : "(untitled)";
|
|
54
|
-
const url = typeof tab.url === "string" ? tab.url : "(no url)";
|
|
55
|
-
const label = typeof tab.label === "string" && tab.label.trim().length > 0 ? tab.label.trim() : undefined;
|
|
56
|
-
const tabSelector = typeof tab.tabId === "string" && tab.tabId.trim().length > 0
|
|
57
|
-
? tab.tabId.trim()
|
|
58
|
-
: label
|
|
59
|
-
? label
|
|
60
|
-
: typeof tab.index === "number"
|
|
61
|
-
? String(tab.index)
|
|
62
|
-
: String(index);
|
|
63
|
-
const labelText = label && label !== tabSelector ? ` label=${redactModelFacingText(label)}` : "";
|
|
64
|
-
const targetId = typeof tab.targetId === "string" && tab.targetId.trim().length > 0 ? tab.targetId.trim() : undefined;
|
|
65
|
-
const targetText = targetId && targetId !== tabSelector ? ` target=${redactModelFacingText(targetId)}` : "";
|
|
66
|
-
return `${marker} [${tabSelector}]${labelText}${targetText} ${title} — ${url}`;
|
|
67
|
-
});
|
|
68
|
-
return lines.join("\n");
|
|
69
|
-
}
|
|
70
|
-
export function getStreamSummary(data) {
|
|
71
|
-
if (data.alreadyEnabled === true) {
|
|
72
|
-
const lines = ["Stream already enabled (idempotent no-op)."];
|
|
73
|
-
if (typeof data.port === "number") {
|
|
74
|
-
lines.push(`Port: ${data.port}`);
|
|
75
|
-
lines.push(`WebSocket URL: ${getStreamWebSocketUrl(data.port)}`);
|
|
76
|
-
}
|
|
77
|
-
lines.push("Run stream status for current connection details or stream disable when streaming is no longer needed.");
|
|
78
|
-
return lines.join("\n");
|
|
79
|
-
}
|
|
80
|
-
if (typeof data.enabled !== "boolean" || typeof data.connected !== "boolean") {
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
const lines = [
|
|
84
|
-
`Enabled: ${data.enabled}`,
|
|
85
|
-
`Connected: ${data.connected}`,
|
|
86
|
-
`Screencasting: ${data.screencasting === true}`,
|
|
87
|
-
];
|
|
88
|
-
if (typeof data.port === "number") {
|
|
89
|
-
lines.push(`Port: ${data.port}`);
|
|
90
|
-
lines.push(`WebSocket URL: ${getStreamWebSocketUrl(data.port)}`);
|
|
91
|
-
lines.push(`Frame format: JSON messages with base64 JPEG frame data`);
|
|
92
|
-
}
|
|
93
|
-
return lines.join("\n");
|
|
94
|
-
}
|
|
95
|
-
function getStreamWebSocketUrl(port) {
|
|
96
|
-
return `ws://127.0.0.1:${port}`;
|
|
97
|
-
}
|
|
98
|
-
export function enrichStreamStatusData(commandInfo, data) {
|
|
99
|
-
if (commandInfo.command !== "stream" || commandInfo.subcommand !== "status" || !isRecord(data) || typeof data.port !== "number") {
|
|
100
|
-
return data;
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
...data,
|
|
104
|
-
frameFormat: "JSON messages with base64 JPEG frame data",
|
|
105
|
-
wsUrl: getStreamWebSocketUrl(data.port),
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
function isClearDiagnosticCommand(commandInfo) {
|
|
109
|
-
return commandInfo.subcommand === "--clear" || commandInfo.commandTokens?.includes("--clear") === true;
|
|
110
|
-
}
|
|
111
|
-
export function formatDiagnosticSummary(commandInfo, data) {
|
|
112
|
-
if (commandInfo.command === "session") {
|
|
113
|
-
const sessions = getArrayField(data, "sessions");
|
|
114
|
-
if (sessions)
|
|
115
|
-
return `Sessions: ${sessions.length}`;
|
|
116
|
-
const session = getStringField(data, "session");
|
|
117
|
-
if (session)
|
|
118
|
-
return `Session: ${session}`;
|
|
119
|
-
}
|
|
120
|
-
if (commandInfo.command === "profiles") {
|
|
121
|
-
const profiles = getArrayField(data, "profiles");
|
|
122
|
-
if (profiles)
|
|
123
|
-
return `Chrome profiles: ${profiles.length}`;
|
|
124
|
-
}
|
|
125
|
-
if (commandInfo.command === "auth") {
|
|
126
|
-
const profiles = getArrayField(data, "profiles");
|
|
127
|
-
if (profiles)
|
|
128
|
-
return `Auth profiles: ${profiles.length}`;
|
|
129
|
-
const name = getStringField(data, "name") ?? getStringField(data, "profile") ?? commandInfo.subcommand;
|
|
130
|
-
if (name && commandInfo.subcommand === "show")
|
|
131
|
-
return `Auth profile: ${name}`;
|
|
132
|
-
if (name && ["save", "login", "delete"].includes(commandInfo.subcommand ?? ""))
|
|
133
|
-
return `Auth ${commandInfo.subcommand}: ${name}`;
|
|
134
|
-
}
|
|
135
|
-
if (commandInfo.command === "cookies") {
|
|
136
|
-
const cookies = getArrayField(data, "cookies");
|
|
137
|
-
if (cookies)
|
|
138
|
-
return `Cookies: ${cookies.length}`;
|
|
139
|
-
const name = getStringField(data, "name");
|
|
140
|
-
if (name)
|
|
141
|
-
return name;
|
|
142
|
-
if (data.set === true)
|
|
143
|
-
return "Cookie set";
|
|
144
|
-
if (data.cleared === true || data.clear === true)
|
|
145
|
-
return "Cookies cleared";
|
|
146
|
-
}
|
|
147
|
-
if (commandInfo.command === "storage") {
|
|
148
|
-
const entries = getArrayField(data, "entries") ?? getArrayField(data, "items");
|
|
149
|
-
if (entries)
|
|
150
|
-
return `Storage entries: ${entries.length}`;
|
|
151
|
-
const key = getStringField(data, "key");
|
|
152
|
-
if (key && (commandInfo.subcommand === "set" || data.set === true || Object.hasOwn(data, "value")))
|
|
153
|
-
return `Storage set: ${key}`;
|
|
154
|
-
if (data.cleared === true || data.clear === true)
|
|
155
|
-
return "Storage cleared";
|
|
156
|
-
}
|
|
157
|
-
if (commandInfo.command === "dialog") {
|
|
158
|
-
const open = typeof data.open === "boolean" ? data.open : undefined;
|
|
159
|
-
if (open !== undefined)
|
|
160
|
-
return open ? "Dialog open" : "No dialog open";
|
|
161
|
-
if (data.accepted === true)
|
|
162
|
-
return "Dialog accepted";
|
|
163
|
-
if (data.dismissed === true)
|
|
164
|
-
return "Dialog dismissed";
|
|
165
|
-
}
|
|
166
|
-
if (commandInfo.command === "frame") {
|
|
167
|
-
const frame = getStringField(data, "frame") ?? getStringField(data, "name") ?? getStringField(data, "selector") ?? commandInfo.subcommand;
|
|
168
|
-
if (frame)
|
|
169
|
-
return `Frame: ${frame}`;
|
|
170
|
-
}
|
|
171
|
-
if (commandInfo.command === "state") {
|
|
172
|
-
const states = getArrayField(data, "states") ?? getArrayField(data, "files");
|
|
173
|
-
if (states)
|
|
174
|
-
return `States: ${states.length}`;
|
|
175
|
-
if (commandInfo.subcommand === "load")
|
|
176
|
-
return undefined;
|
|
177
|
-
const stateName = getStringField(data, "name") ?? getStringField(data, "file") ?? getStringField(data, "filename") ?? getStringField(data, "path") ?? commandInfo.subcommand;
|
|
178
|
-
if (stateName)
|
|
179
|
-
return `State ${commandInfo.subcommand ?? "result"}: ${stateName}`;
|
|
180
|
-
}
|
|
181
|
-
if (commandInfo.command === "network") {
|
|
182
|
-
if (commandInfo.subcommand === "requests") {
|
|
183
|
-
const requests = getArrayField(data, "requests");
|
|
184
|
-
if (requests)
|
|
185
|
-
return isClearDiagnosticCommand(commandInfo) ? `Network requests reset: ${requests.length} cleared` : `Network requests: ${requests.length}`;
|
|
186
|
-
}
|
|
187
|
-
if (commandInfo.subcommand === "route") {
|
|
188
|
-
const routed = getStringField(data, "routed") ?? getStringField(data, "url") ?? getStringField(data, "pattern");
|
|
189
|
-
return routed ? `Network route: ${redactSensitiveText(routed)}` : "Network route configured";
|
|
190
|
-
}
|
|
191
|
-
if (commandInfo.subcommand === "unroute") {
|
|
192
|
-
const unrouted = getStringField(data, "unrouted") ?? getStringField(data, "url") ?? getStringField(data, "pattern");
|
|
193
|
-
return unrouted ? `Network unroute: ${redactSensitiveText(unrouted)}` : "Network route removed";
|
|
194
|
-
}
|
|
195
|
-
if (commandInfo.subcommand === "har") {
|
|
196
|
-
const state = getStringField(data, "state") ?? getStringField(data, "status") ?? commandInfo.subcommand;
|
|
197
|
-
return `Network HAR: ${state}`;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
if (commandInfo.command === "diff") {
|
|
201
|
-
if (commandInfo.subcommand === "snapshot")
|
|
202
|
-
return "Snapshot diff completed";
|
|
203
|
-
if (commandInfo.subcommand === "url")
|
|
204
|
-
return "URL diff completed";
|
|
205
|
-
}
|
|
206
|
-
if (["trace", "profiler"].includes(commandInfo.command ?? "")) {
|
|
207
|
-
const state = getStringField(data, "state") ?? getStringField(data, "status") ?? commandInfo.subcommand;
|
|
208
|
-
if (state)
|
|
209
|
-
return `${commandInfo.command === "trace" ? "Trace" : "Profiler"}: ${state}`;
|
|
210
|
-
}
|
|
211
|
-
if (commandInfo.command === "highlight")
|
|
212
|
-
return "Element highlighted";
|
|
213
|
-
if (commandInfo.command === "inspect")
|
|
214
|
-
return "DevTools inspect opened";
|
|
215
|
-
if (commandInfo.command === "clipboard")
|
|
216
|
-
return `Clipboard ${commandInfo.subcommand ?? "completed"}`;
|
|
217
|
-
if (commandInfo.command === "stream") {
|
|
218
|
-
if (commandInfo.subcommand === "enable") {
|
|
219
|
-
if (data.alreadyEnabled === true)
|
|
220
|
-
return "Stream already enabled";
|
|
221
|
-
const port = typeof data.port === "number" ? ` on port ${data.port}` : "";
|
|
222
|
-
return `Stream enabled${port}`;
|
|
223
|
-
}
|
|
224
|
-
if (commandInfo.subcommand === "disable")
|
|
225
|
-
return "Stream disabled";
|
|
226
|
-
}
|
|
227
|
-
if (commandInfo.command === "chat")
|
|
228
|
-
return "Chat response";
|
|
229
|
-
if (commandInfo.command === "console") {
|
|
230
|
-
const messages = getArrayField(data, "messages");
|
|
231
|
-
if (messages)
|
|
232
|
-
return isClearDiagnosticCommand(commandInfo) ? `Console reset: ${messages.length} cleared` : `Console messages: ${messages.length}`;
|
|
233
|
-
}
|
|
234
|
-
if (commandInfo.command === "errors") {
|
|
235
|
-
const errors = getArrayField(data, "errors");
|
|
236
|
-
if (errors)
|
|
237
|
-
return isClearDiagnosticCommand(commandInfo) ? `Page errors reset: ${errors.length} cleared` : `Page errors: ${errors.length}`;
|
|
238
|
-
}
|
|
239
|
-
if (commandInfo.command === "dashboard") {
|
|
240
|
-
if (typeof data.port === "number")
|
|
241
|
-
return `Dashboard running on port ${data.port}`;
|
|
242
|
-
if (data.stopped === true)
|
|
243
|
-
return "Dashboard stopped";
|
|
244
|
-
if (data.stopped === false) {
|
|
245
|
-
const reason = getStringField(data, "reason");
|
|
246
|
-
return reason ? `Dashboard not stopped: ${reason}` : "Dashboard not stopped";
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
if (commandInfo.command === "doctor") {
|
|
250
|
-
const status = getStringField(data, "status") ?? getStringField(data, "result");
|
|
251
|
-
if (status)
|
|
252
|
-
return `Doctor: ${status}`;
|
|
253
|
-
const checks = getArrayField(data, "checks") ?? getArrayField(data, "issues") ?? getArrayField(data, "problems");
|
|
254
|
-
if (checks)
|
|
255
|
-
return `Doctor: ${formatCount(checks.length, "item")}`;
|
|
256
|
-
}
|
|
257
|
-
return undefined;
|
|
258
|
-
}
|
|
259
|
-
function formatSessionText(data) {
|
|
260
|
-
const sessions = getArrayField(data, "sessions");
|
|
261
|
-
if (sessions) {
|
|
262
|
-
if (sessions.length === 0)
|
|
263
|
-
return "No active sessions.";
|
|
264
|
-
return sessions
|
|
265
|
-
.map((item, index) => {
|
|
266
|
-
if (!isRecord(item))
|
|
267
|
-
return `${index + 1}. ${stringifyModelFacing(item)}`;
|
|
268
|
-
const name = redactModelFacingText(getStringField(item, "name") ?? getStringField(item, "session") ?? getStringField(item, "id") ?? `(session ${index + 1})`);
|
|
269
|
-
const active = item.active === true;
|
|
270
|
-
const url = getStringField(item, "url");
|
|
271
|
-
const title = getStringField(item, "title");
|
|
272
|
-
const label = getStringField(item, "label");
|
|
273
|
-
const tabCount = typeof item.tabCount === "number" ? `${item.tabCount} tab${item.tabCount === 1 ? "" : "s"}` : undefined;
|
|
274
|
-
const metadata = [
|
|
275
|
-
`active=${active ? "true" : "false"}`,
|
|
276
|
-
label ? `label=${redactModelFacingText(label)}` : undefined,
|
|
277
|
-
title ? `title=${redactSensitiveText(title)}` : undefined,
|
|
278
|
-
url ? `url=${redactSensitiveText(url)}` : undefined,
|
|
279
|
-
tabCount,
|
|
280
|
-
].filter(Boolean).join("; ");
|
|
281
|
-
return `${index + 1}. name=${name}${active ? " *active*" : ""}; ${metadata}`;
|
|
282
|
-
})
|
|
283
|
-
.join("\n");
|
|
284
|
-
}
|
|
285
|
-
if (typeof data.active === "boolean") {
|
|
286
|
-
const runtime = data.runtime;
|
|
287
|
-
const browser = isRecord(runtime) && isRecord(runtime.browser) ? runtime.browser : undefined;
|
|
288
|
-
const identity = [
|
|
289
|
-
`Daemon: ${data.active ? "active" : "inactive"}; PID: ${data.pid ?? "unknown"}`,
|
|
290
|
-
`Browser: ${browser?.status ?? "unknown"}; alive: ${browser?.alive ?? "unknown"}; Chrome PID: ${browser?.pid ?? "unknown"}`,
|
|
291
|
-
`Exact profile: ${browser?.userDataDir ?? "unknown"}`,
|
|
292
|
-
`Native browser ownership: ${browser?.ownership ?? "unknown"}; Pi cleanup ownership: ${data.piCleanupOwnership ?? "unknown"}`,
|
|
293
|
-
].join("\n");
|
|
294
|
-
return `${redactModelFacingText(identity)}\n\n${stringifyModelFacing({
|
|
295
|
-
...Object.fromEntries(["session", "namespace", "socketDir", "active", "pid", "version", "runtimeError"].map((key) => [key, data[key]])),
|
|
296
|
-
// Native runtime also includes restore check URLs, text and code; show status/identity only.
|
|
297
|
-
runtime: isRecord(runtime) ? Object.fromEntries([
|
|
298
|
-
"session", "namespace", "socketDir", "backgroundPid", "browserLaunched", "browser", "recording", "capabilities", "pageCount", "engine", "launchHash",
|
|
299
|
-
"compatibilityStatus", "restoreKey", "restoreStatus", "restoreLoadedPath", "restoreValidationPending",
|
|
300
|
-
"restoreSave", "saveStatus", "restoreSavedPath",
|
|
301
|
-
].map((key) => [key, runtime[key]])) : runtime,
|
|
302
|
-
})}`;
|
|
303
|
-
}
|
|
304
|
-
const session = getStringField(data, "session");
|
|
305
|
-
return session ? `Current session: ${redactModelFacingText(session)}` : undefined;
|
|
306
|
-
}
|
|
307
|
-
export function formatProfilesText(profiles, label) {
|
|
308
|
-
if (profiles.length === 0)
|
|
309
|
-
return `No ${label}.`;
|
|
310
|
-
return profiles
|
|
311
|
-
.map((item, index) => {
|
|
312
|
-
if (!isRecord(item))
|
|
313
|
-
return `${index + 1}. ${stringifyModelFacing(item)}`;
|
|
314
|
-
const name = redactModelFacingText(getStringField(item, "name") ?? getStringField(item, "profile") ?? `(unnamed ${index + 1})`);
|
|
315
|
-
const directory = getStringField(item, "directory") ?? getStringField(item, "path");
|
|
316
|
-
return directory ? `${index + 1}. ${name} (${redactModelFacingText(directory)})` : `${index + 1}. ${name}`;
|
|
317
|
-
})
|
|
318
|
-
.join("\n");
|
|
319
|
-
}
|
|
320
|
-
function formatAuthShowText(data) {
|
|
321
|
-
const lines = AUTH_SHOW_SAFE_FIELDS.flatMap((key) => {
|
|
322
|
-
const value = data[key];
|
|
323
|
-
return typeof value === "string" && value.trim().length > 0 ? [`${key}: ${redactModelFacingText(value.trim())}`] : [];
|
|
324
|
-
});
|
|
325
|
-
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
326
|
-
}
|
|
327
|
-
function getPreviewCandidate(item, keys) {
|
|
328
|
-
for (const key of keys) {
|
|
329
|
-
const value = item[key];
|
|
330
|
-
if (value !== undefined && value !== null && value !== "")
|
|
331
|
-
return value;
|
|
332
|
-
}
|
|
333
|
-
return undefined;
|
|
334
|
-
}
|
|
335
|
-
function formatNetworkPreviewValue(value, maxChars) {
|
|
336
|
-
if (value === undefined || value === null)
|
|
337
|
-
return undefined;
|
|
338
|
-
const redacted = redactSensitiveValue(value);
|
|
339
|
-
const raw = typeof redacted === "string" ? redacted : stringifyUnknown(redacted);
|
|
340
|
-
const normalized = raw.replace(/\s+/g, " ").trim();
|
|
341
|
-
if (normalized.length === 0)
|
|
342
|
-
return undefined;
|
|
343
|
-
return truncateText(redactSensitiveText(normalized), maxChars);
|
|
344
|
-
}
|
|
345
|
-
function appendNetworkPreview(lines, label, value, maxChars) {
|
|
346
|
-
const preview = formatNetworkPreviewValue(value, maxChars);
|
|
347
|
-
if (!preview)
|
|
348
|
-
return;
|
|
349
|
-
lines.push(` ${label}: ${preview}`);
|
|
350
|
-
}
|
|
351
|
-
function formatNetworkRequestLine(item, index) {
|
|
352
|
-
const method = getStringField(item, "method") ?? "GET";
|
|
353
|
-
const status = typeof item.status === "number" ? String(item.status) : "pending";
|
|
354
|
-
const type = getStringField(item, "resourceType") ?? getStringField(item, "mimeType");
|
|
355
|
-
const url = getStringField(item, "url") ?? "(no url)";
|
|
356
|
-
const requestId = getStringField(item, "requestId") ?? getStringField(item, "id");
|
|
357
|
-
const idText = requestId ? ` [${redactSensitiveText(requestId)}]` : "";
|
|
358
|
-
const failureClassification = classifyNetworkRequestFailure(item);
|
|
359
|
-
const impactText = failureClassification ? ` [${failureClassification.impact}: ${failureClassification.reason}]` : "";
|
|
360
|
-
const lines = [`${index + 1}. ${status} ${method} ${truncateText(redactSensitiveText(url), 180)}${type ? ` (${type})` : ""}${idText}${impactText}`];
|
|
361
|
-
appendNetworkPreview(lines, "Payload", getPreviewCandidate(item, NETWORK_PREVIEW_FIELD_CANDIDATES.request), NETWORK_BODY_PREVIEW_MAX_CHARS);
|
|
362
|
-
appendNetworkPreview(lines, "Response", getPreviewCandidate(item, NETWORK_PREVIEW_FIELD_CANDIDATES.response), NETWORK_BODY_PREVIEW_MAX_CHARS);
|
|
363
|
-
appendNetworkPreview(lines, "Error", getPreviewCandidate(item, NETWORK_PREVIEW_FIELD_CANDIDATES.error), NETWORK_ERROR_PREVIEW_MAX_CHARS);
|
|
364
|
-
return lines;
|
|
365
|
-
}
|
|
366
|
-
function formatNetworkRequestsText(data, commandInfo) {
|
|
367
|
-
const requests = getArrayField(data, "requests");
|
|
368
|
-
if (isClearDiagnosticCommand(commandInfo) && data.cleared === true && !requests)
|
|
369
|
-
return "Network request buffer cleared.";
|
|
370
|
-
if (!requests)
|
|
371
|
-
return undefined;
|
|
372
|
-
if (isClearDiagnosticCommand(commandInfo)) {
|
|
373
|
-
return requests.length === 0
|
|
374
|
-
? "Network request buffer cleared; no prior request rows were returned. This reset output is not evidence of current-page network activity."
|
|
375
|
-
: `Network request buffer cleared; upstream returned ${requests.length} cleared/stale row${requests.length === 1 ? "" : "s"}. Treat these as reset output, not current-page request failures.`;
|
|
376
|
-
}
|
|
377
|
-
if (requests.length === 0)
|
|
378
|
-
return "No network requests captured. Scope: upstream session aggregate unless the upstream command output says it was cleared or filtered for this page.";
|
|
379
|
-
const shown = ["Scope: upstream session aggregate unless the upstream command output says it was cleared or filtered for this page; do not attribute old requests to the current page without URL/time evidence."];
|
|
380
|
-
const indexedRequests = requests.map((item, index) => ({ index, item }));
|
|
381
|
-
const artifactNoiseRequests = indexedRequests.filter((indexed) => isRecord(indexed.item) && isNetworkArtifactNoiseRequest(indexed.item));
|
|
382
|
-
const previewRequests = indexedRequests.filter((indexed) => !(isRecord(indexed.item) && isNetworkArtifactNoiseRequest(indexed.item)));
|
|
383
|
-
const networkFailureSummary = summarizeNetworkFailures(previewRequests.map((indexed) => indexed.item));
|
|
384
|
-
if (networkFailureSummary.totalCount > 0) {
|
|
385
|
-
shown.push(`Network failure summary: ${networkFailureSummary.actionableCount} actionable, ${networkFailureSummary.benignCount} benign low-impact (${networkFailureSummary.totalCount} total).`);
|
|
386
|
-
}
|
|
387
|
-
const failedRequests = [];
|
|
388
|
-
const normalRequests = [];
|
|
389
|
-
for (const indexed of previewRequests) {
|
|
390
|
-
if (isRecord(indexed.item) && classifyNetworkRequestFailure(indexed.item))
|
|
391
|
-
failedRequests.push(indexed);
|
|
392
|
-
else
|
|
393
|
-
normalRequests.push(indexed);
|
|
394
|
-
}
|
|
395
|
-
if (artifactNoiseRequests.length > 0) {
|
|
396
|
-
shown.push(`Diagnostic noise hidden from preview: ${artifactNoiseRequests.length} data:image/artifact request row${artifactNoiseRequests.length === 1 ? "" : "s"}; raw rows remain in details.data.requests.`);
|
|
397
|
-
}
|
|
398
|
-
failedRequests.sort((left, right) => {
|
|
399
|
-
const leftClassification = isRecord(left.item) ? classifyNetworkRequestFailure(left.item) : undefined;
|
|
400
|
-
const rightClassification = isRecord(right.item) ? classifyNetworkRequestFailure(right.item) : undefined;
|
|
401
|
-
const leftRank = leftClassification?.impact === "actionable" ? 0 : 1;
|
|
402
|
-
const rightRank = rightClassification?.impact === "actionable" ? 0 : 1;
|
|
403
|
-
return leftRank - rightRank || left.index - right.index;
|
|
404
|
-
});
|
|
405
|
-
const prioritizedRequests = [...failedRequests, ...normalRequests];
|
|
406
|
-
shown.push(...prioritizedRequests.slice(0, DIAGNOSTIC_REQUEST_PREVIEW_LIMIT).flatMap(({ item, index }) => {
|
|
407
|
-
if (!isRecord(item))
|
|
408
|
-
return [`${index + 1}. ${stringifyModelFacing(item)}`];
|
|
409
|
-
return formatNetworkRequestLine(item, index);
|
|
410
|
-
}));
|
|
411
|
-
const omittedPreviewCount = Math.max(0, prioritizedRequests.length - DIAGNOSTIC_REQUEST_PREVIEW_LIMIT);
|
|
412
|
-
if (omittedPreviewCount > 0) {
|
|
413
|
-
shown.push(`... (${omittedPreviewCount} additional non-noise requests omitted from preview; failed requests are shown first when present)`);
|
|
414
|
-
}
|
|
415
|
-
return shown.join("\n");
|
|
416
|
-
}
|
|
417
|
-
function formatNetworkRequestText(data) {
|
|
418
|
-
if (!getStringField(data, "url") && !getStringField(data, "requestId") && !getStringField(data, "id")) {
|
|
419
|
-
return undefined;
|
|
420
|
-
}
|
|
421
|
-
return formatNetworkRequestLine(data, 0).join("\n");
|
|
422
|
-
}
|
|
423
|
-
function getSafeNetworkActionValue(value) {
|
|
424
|
-
if (!value)
|
|
425
|
-
return undefined;
|
|
426
|
-
const trimmed = value.trim();
|
|
427
|
-
if (trimmed.length === 0 || redactSensitiveText(trimmed) !== trimmed)
|
|
428
|
-
return undefined;
|
|
429
|
-
return trimmed;
|
|
430
|
-
}
|
|
431
|
-
function getNetworkRequestId(item) {
|
|
432
|
-
return getSafeNetworkActionValue(getStringField(item, "requestId") ?? getStringField(item, "id"));
|
|
433
|
-
}
|
|
434
|
-
function isSensitiveNetworkPathSegment(segment) {
|
|
435
|
-
const normalized = segment.toLowerCase();
|
|
436
|
-
return normalized === "auth" || NETWORK_FILTER_SENSITIVE_SEGMENT_TERMS.some((term) => normalized.includes(term));
|
|
437
|
-
}
|
|
438
|
-
function pathFilterMayExposeSensitiveSegment(filter) {
|
|
439
|
-
const decoded = (() => {
|
|
440
|
-
try {
|
|
441
|
-
return decodeURIComponent(filter);
|
|
442
|
-
}
|
|
443
|
-
catch {
|
|
444
|
-
return filter;
|
|
445
|
-
}
|
|
446
|
-
})();
|
|
447
|
-
return decoded.split("/").some((segment) => isSensitiveNetworkPathSegment(segment) || NETWORK_FILTER_OPAQUE_SEGMENT_PATTERN.test(segment));
|
|
448
|
-
}
|
|
449
|
-
function getNetworkRequestPathFilter(item) {
|
|
450
|
-
const url = getStringField(item, "url");
|
|
451
|
-
if (!url)
|
|
452
|
-
return undefined;
|
|
453
|
-
let filter;
|
|
454
|
-
try {
|
|
455
|
-
filter = new URL(url).pathname;
|
|
456
|
-
}
|
|
457
|
-
catch {
|
|
458
|
-
filter = url.split(/[?#]/, 1)[0];
|
|
459
|
-
}
|
|
460
|
-
filter = filter?.trim();
|
|
461
|
-
if (!filter || filter === "/" || filter.length > NETWORK_FILTER_MAX_CHARS || pathFilterMayExposeSensitiveSegment(filter))
|
|
462
|
-
return undefined;
|
|
463
|
-
return getSafeNetworkActionValue(filter);
|
|
464
|
-
}
|
|
465
|
-
function getNetworkRequestActionCandidate(item) {
|
|
466
|
-
if (isNetworkArtifactNoiseRequest(item))
|
|
467
|
-
return undefined;
|
|
468
|
-
const requestId = getNetworkRequestId(item);
|
|
469
|
-
if (!requestId)
|
|
470
|
-
return undefined;
|
|
471
|
-
const classification = classifyNetworkRequestFailure(item);
|
|
472
|
-
const kind = classification?.impact === "actionable"
|
|
473
|
-
? "actionable"
|
|
474
|
-
: classification?.impact === "benign"
|
|
475
|
-
? "benign"
|
|
476
|
-
: isApiLikeNetworkRequest(item)
|
|
477
|
-
? "api"
|
|
478
|
-
: "request";
|
|
479
|
-
return { filter: getNetworkRequestPathFilter(item), item, kind, requestId };
|
|
480
|
-
}
|
|
481
|
-
function chooseNetworkRequestActionCandidate(candidates) {
|
|
482
|
-
return candidates.find((candidate) => candidate.kind === "actionable")
|
|
483
|
-
?? candidates.find((candidate) => candidate.kind === "api")
|
|
484
|
-
?? candidates.find((candidate) => candidate.kind === "benign")
|
|
485
|
-
?? candidates[0];
|
|
486
|
-
}
|
|
487
|
-
function formatNetworkRequestActionDescriptor(candidate) {
|
|
488
|
-
const method = getStringField(candidate.item, "method") ?? "GET";
|
|
489
|
-
const status = typeof candidate.item.status === "number" ? String(candidate.item.status) : "pending";
|
|
490
|
-
const target = candidate.filter ? ` ${candidate.filter}` : "";
|
|
491
|
-
return `${status} ${method}${target} [${candidate.requestId}]`;
|
|
492
|
-
}
|
|
493
|
-
function getNetworkRequestDetailActionId(candidate) {
|
|
494
|
-
if (candidate.kind === "actionable")
|
|
495
|
-
return "inspect-actionable-network-request";
|
|
496
|
-
if (candidate.kind === "benign")
|
|
497
|
-
return "inspect-benign-network-request";
|
|
498
|
-
return "inspect-network-request";
|
|
499
|
-
}
|
|
500
|
-
export function formatNetworkRouteDiagnosticsText(diagnostics) {
|
|
501
|
-
if (!diagnostics || diagnostics.length === 0)
|
|
502
|
-
return undefined;
|
|
503
|
-
const lines = ["Network route diagnostics:"];
|
|
504
|
-
for (const diagnostic of diagnostics) {
|
|
505
|
-
const target = diagnostic.requestId ? `[${diagnostic.requestId}] ${diagnostic.requestUrl ?? "request"}` : diagnostic.requestUrl ?? "request";
|
|
506
|
-
lines.push(`- ${diagnostic.reason}: ${target} matched route ${diagnostic.routePattern} (${diagnostic.mode}).`);
|
|
507
|
-
}
|
|
508
|
-
lines.push("If this route is intended as a mock, inspect the request/headers and treat failed, pending, or CORS-looking rows as unfulfilled until a mocked response is observed.");
|
|
509
|
-
return lines.join("\n");
|
|
510
|
-
}
|
|
511
|
-
function buildNetworkRouteDiagnosticsNextActions(diagnostics, sessionName) {
|
|
512
|
-
const diagnostic = diagnostics?.find((item) => item.requestId) ?? diagnostics?.[0];
|
|
513
|
-
if (!diagnostic)
|
|
514
|
-
return undefined;
|
|
515
|
-
const actions = [];
|
|
516
|
-
if (diagnostic.requestId) {
|
|
517
|
-
actions.push({
|
|
518
|
-
id: "inspect-routed-network-request",
|
|
519
|
-
params: { args: withOptionalSessionArgs(sessionName, ["network", "request", diagnostic.requestId]) },
|
|
520
|
-
reason: `Inspect the routed request ${diagnostic.requestId} before assuming the route mock fulfilled normally.`,
|
|
521
|
-
safety: "Read-only request diagnostic; look for failed status, pending state, CORS/preflight errors, response body, and headers.",
|
|
522
|
-
tool: "agent_browser",
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
actions.push({
|
|
526
|
-
id: "start-network-har-capture-for-route-mock",
|
|
527
|
-
params: { args: withOptionalSessionArgs(sessionName, ["network", "har", "start"]) },
|
|
528
|
-
reason: "Capture a HAR before reproducing the route mock so pending/CORS behavior has request and response headers.",
|
|
529
|
-
safety: "HARs can contain URLs and headers; stop to an explicit path and avoid sharing sensitive captures.",
|
|
530
|
-
tool: "agent_browser",
|
|
531
|
-
});
|
|
532
|
-
return actions;
|
|
533
|
-
}
|
|
534
|
-
export function buildNetworkRequestsNextActions(data, sessionName, routeDiagnostics) {
|
|
535
|
-
if (!isRecord(data))
|
|
536
|
-
return undefined;
|
|
537
|
-
const requests = getArrayField(data, "requests");
|
|
538
|
-
if (!requests)
|
|
539
|
-
return undefined;
|
|
540
|
-
const candidates = requests.flatMap((item) => {
|
|
541
|
-
if (!isRecord(item))
|
|
542
|
-
return [];
|
|
543
|
-
const candidate = getNetworkRequestActionCandidate(item);
|
|
544
|
-
return candidate ? [candidate] : [];
|
|
545
|
-
});
|
|
546
|
-
const selected = chooseNetworkRequestActionCandidate(candidates);
|
|
547
|
-
if (!selected)
|
|
548
|
-
return undefined;
|
|
549
|
-
const descriptor = formatNetworkRequestActionDescriptor(selected);
|
|
550
|
-
const actions = [
|
|
551
|
-
{
|
|
552
|
-
id: getNetworkRequestDetailActionId(selected),
|
|
553
|
-
params: { args: withOptionalSessionArgs(sessionName, ["network", "request", selected.requestId]) },
|
|
554
|
-
reason: `Inspect full request details for ${descriptor}.`,
|
|
555
|
-
safety: "Read-only network diagnostic; request inspection must not replace the active page/ref context.",
|
|
556
|
-
tool: "agent_browser",
|
|
557
|
-
},
|
|
558
|
-
];
|
|
559
|
-
if (selected.kind === "actionable") {
|
|
560
|
-
actions.push({
|
|
561
|
-
id: "trace-actionable-network-source",
|
|
562
|
-
params: { requestId: selected.requestId, ...(sessionName ? { session: sessionName } : {}) },
|
|
563
|
-
reason: `Look for local source candidates related to ${descriptor}.`,
|
|
564
|
-
safety: "Read-only experimental helper; enable network with agent_browser_tools when this tool is inactive. It reports bounded candidates and may miss bundled or dynamic call sites.",
|
|
565
|
-
tool: "agent_browser_network_source",
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
if (selected.filter) {
|
|
569
|
-
actions.push({
|
|
570
|
-
id: "filter-network-requests-by-path",
|
|
571
|
-
params: { args: withOptionalSessionArgs(sessionName, ["network", "requests", "--filter", selected.filter]) },
|
|
572
|
-
reason: `List captured requests matching ${selected.filter}.`,
|
|
573
|
-
safety: "Read-only request-list filter; absence from a compact preview is not proof the request did not happen.",
|
|
574
|
-
tool: "agent_browser",
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
actions.push({
|
|
578
|
-
id: "clear-network-requests-before-repro",
|
|
579
|
-
params: { args: withOptionalSessionArgs(sessionName, ["network", "requests", "--clear"]) },
|
|
580
|
-
reason: "Clear the aggregate request buffer before reproducing the current-page network behavior.",
|
|
581
|
-
safety: "This mutates only diagnostic buffers for the session; capture or inspect needed old rows first.",
|
|
582
|
-
tool: "agent_browser",
|
|
583
|
-
});
|
|
584
|
-
actions.push({
|
|
585
|
-
id: "start-network-har-capture",
|
|
586
|
-
params: { args: withOptionalSessionArgs(sessionName, ["network", "har", "start"]) },
|
|
587
|
-
reason: "Start HAR capture before reproducing the network behavior again.",
|
|
588
|
-
safety: "HARs can contain URLs and headers; stop to an explicit path, inspect metadata, and avoid sharing sensitive captures.",
|
|
589
|
-
tool: "agent_browser",
|
|
590
|
-
});
|
|
591
|
-
return [...(buildNetworkRouteDiagnosticsNextActions(routeDiagnostics, sessionName) ?? []), ...actions].slice(0, NETWORK_NEXT_ACTION_LIMIT);
|
|
592
|
-
}
|
|
593
|
-
export function buildStreamNextActions(commandInfo, data, sessionName) {
|
|
594
|
-
if (commandInfo.command !== "stream" || commandInfo.subcommand !== "enable" || !isRecord(data) || data.alreadyEnabled !== true)
|
|
595
|
-
return undefined;
|
|
596
|
-
return [
|
|
597
|
-
{
|
|
598
|
-
id: "check-stream-status-after-noop",
|
|
599
|
-
params: { args: withOptionalSessionArgs(sessionName, ["stream", "status"]) },
|
|
600
|
-
reason: "Read current stream port and connection details after the idempotent enable no-op.",
|
|
601
|
-
safety: "Read-only stream diagnostic.",
|
|
602
|
-
tool: "agent_browser",
|
|
603
|
-
},
|
|
604
|
-
{
|
|
605
|
-
id: "disable-existing-stream-when-done",
|
|
606
|
-
params: { args: withOptionalSessionArgs(sessionName, ["stream", "disable"]) },
|
|
607
|
-
reason: "Disable the existing stream when it is no longer needed.",
|
|
608
|
-
safety: "Only run when no other workflow is relying on the current stream.",
|
|
609
|
-
tool: "agent_browser",
|
|
610
|
-
},
|
|
611
|
-
];
|
|
612
|
-
}
|
|
613
|
-
function formatConsoleText(data, commandInfo) {
|
|
614
|
-
const messages = getArrayField(data, "messages");
|
|
615
|
-
if (isClearDiagnosticCommand(commandInfo) && data.cleared === true && !messages)
|
|
616
|
-
return "Console buffer cleared.";
|
|
617
|
-
if (!messages)
|
|
618
|
-
return undefined;
|
|
619
|
-
if (isClearDiagnosticCommand(commandInfo)) {
|
|
620
|
-
return messages.length === 0
|
|
621
|
-
? "Console buffer cleared; no prior message rows were returned. This reset output is not evidence of current-page console activity."
|
|
622
|
-
: `Console buffer cleared; upstream returned ${messages.length} cleared/stale message row${messages.length === 1 ? "" : "s"}. Treat these as reset output, not current-page console errors.`;
|
|
623
|
-
}
|
|
624
|
-
if (messages.length === 0)
|
|
625
|
-
return "No console messages. Scope: upstream session aggregate unless the upstream command output says it was cleared or filtered for this page.";
|
|
626
|
-
const shown = ["Scope: upstream session aggregate unless the upstream command output says it was cleared or filtered for this page; do not attribute old messages to the current page without URL/time evidence."];
|
|
627
|
-
shown.push(...messages.slice(0, DIAGNOSTIC_LOG_PREVIEW_LIMIT).map((item, index) => {
|
|
628
|
-
if (!isRecord(item))
|
|
629
|
-
return `${index + 1}. ${stringifyModelFacing(item)}`;
|
|
630
|
-
const type = redactModelFacingText(getStringField(item, "type") ?? "message");
|
|
631
|
-
const text = getStringField(item, "text") ?? stringifyModelFacing(item);
|
|
632
|
-
return `${index + 1}. [${type}] ${firstLine(redactModelFacingText(text).replace(/\s+/g, " ").trim(), 220)}`;
|
|
633
|
-
}));
|
|
634
|
-
const previewedMessageCount = Math.min(messages.length, DIAGNOSTIC_LOG_PREVIEW_LIMIT);
|
|
635
|
-
if (messages.length > previewedMessageCount) {
|
|
636
|
-
shown.push(`... (${messages.length - previewedMessageCount} additional console messages omitted from preview)`);
|
|
637
|
-
}
|
|
638
|
-
return shown.join("\n");
|
|
639
|
-
}
|
|
640
|
-
function formatA11yText(data) {
|
|
641
|
-
const counts = isRecord(data.counts) ? data.counts : undefined;
|
|
642
|
-
const violations = getArrayField(data, "violations") ?? [];
|
|
643
|
-
const incomplete = getArrayField(data, "incomplete") ?? [];
|
|
644
|
-
if (!counts && violations.length === 0 && incomplete.length === 0)
|
|
645
|
-
return undefined;
|
|
646
|
-
const lines = [];
|
|
647
|
-
const axeVersion = getStringField(data, "axeVersion");
|
|
648
|
-
if (axeVersion)
|
|
649
|
-
lines.push(`axe-core ${redactModelFacingText(axeVersion)}`);
|
|
650
|
-
const url = getStringField(data, "url");
|
|
651
|
-
if (url)
|
|
652
|
-
lines.push(`URL: ${redactModelFacingText(url)}`);
|
|
653
|
-
const violationCount = typeof counts?.violations === "number" ? counts.violations : violations.length;
|
|
654
|
-
const incompleteCount = typeof counts?.incomplete === "number" ? counts.incomplete : incomplete.length;
|
|
655
|
-
const passCount = typeof counts?.passes === "number" ? counts.passes : undefined;
|
|
656
|
-
const inapplicableCount = typeof counts?.inapplicable === "number" ? counts.inapplicable : undefined;
|
|
657
|
-
const countParts = [`${violationCount} violation${violationCount === 1 ? "" : "s"}`, `${incompleteCount} incomplete`];
|
|
658
|
-
if (passCount !== undefined)
|
|
659
|
-
countParts.push(`${passCount} passes`);
|
|
660
|
-
if (inapplicableCount !== undefined)
|
|
661
|
-
countParts.push(`${inapplicableCount} inapplicable`);
|
|
662
|
-
lines.push(`A11y audit: ${countParts.join(", ")}.`);
|
|
663
|
-
const previewLimit = Math.min(10, DIAGNOSTIC_LOG_PREVIEW_LIMIT);
|
|
664
|
-
const preview = violations.slice(0, previewLimit).map((item, index) => {
|
|
665
|
-
if (!isRecord(item))
|
|
666
|
-
return `${index + 1}. ${stringifyModelFacing(item)}`;
|
|
667
|
-
const id = redactModelFacingText(getStringField(item, "id") ?? "rule");
|
|
668
|
-
const impact = redactModelFacingText(getStringField(item, "impact") ?? "unknown");
|
|
669
|
-
const help = firstLine(redactModelFacingText(getStringField(item, "help") ?? "").replace(/\s+/g, " ").trim(), 160);
|
|
670
|
-
const nodeCount = typeof item.nodeCount === "number" ? item.nodeCount : getArrayField(item, "nodes")?.length;
|
|
671
|
-
const nodePart = typeof nodeCount === "number" ? `, ${nodeCount} node${nodeCount === 1 ? "" : "s"}` : "";
|
|
672
|
-
return `${index + 1}. [${impact}] ${id}${nodePart}${help ? ` — ${help}` : ""}`;
|
|
673
|
-
});
|
|
674
|
-
lines.push(...preview);
|
|
675
|
-
if (violations.length > preview.length) {
|
|
676
|
-
lines.push(`... (${violations.length - preview.length} additional violations omitted from preview)`);
|
|
677
|
-
}
|
|
678
|
-
if (incompleteCount > 0) {
|
|
679
|
-
lines.push(`${incompleteCount} incomplete check${incompleteCount === 1 ? "" : "s"} need manual review (see details.data.incomplete).`);
|
|
680
|
-
}
|
|
681
|
-
return lines.join("\n");
|
|
682
|
-
}
|
|
683
|
-
function formatErrorsText(data, commandInfo) {
|
|
684
|
-
const errors = getArrayField(data, "errors");
|
|
685
|
-
if (!errors)
|
|
686
|
-
return undefined;
|
|
687
|
-
if (isClearDiagnosticCommand(commandInfo)) {
|
|
688
|
-
return errors.length === 0
|
|
689
|
-
? "Page error buffer cleared; no prior error rows were returned. This reset output is not evidence of current-page errors."
|
|
690
|
-
: `Page error buffer cleared; upstream returned ${errors.length} cleared/stale error row${errors.length === 1 ? "" : "s"}. Treat these as reset output, not current-page errors.`;
|
|
691
|
-
}
|
|
692
|
-
if (errors.length === 0)
|
|
693
|
-
return "No page errors.";
|
|
694
|
-
const shown = errors.slice(0, DIAGNOSTIC_LOG_PREVIEW_LIMIT).map((item, index) => {
|
|
695
|
-
if (!isRecord(item))
|
|
696
|
-
return `${index + 1}. ${stringifyModelFacing(item)}`;
|
|
697
|
-
const text = getStringField(item, "text") ?? stringifyModelFacing(item);
|
|
698
|
-
const location = [
|
|
699
|
-
getStringField(item, "url"),
|
|
700
|
-
typeof item.line === "number" ? `line ${item.line}` : undefined,
|
|
701
|
-
typeof item.column === "number" ? `column ${item.column}` : undefined,
|
|
702
|
-
]
|
|
703
|
-
.filter(Boolean)
|
|
704
|
-
.map((item) => redactModelFacingText(String(item)))
|
|
705
|
-
.join(":");
|
|
706
|
-
const safeText = firstLine(redactModelFacingText(text), 220);
|
|
707
|
-
return location ? `${index + 1}. ${safeText} (${location})` : `${index + 1}. ${safeText}`;
|
|
708
|
-
});
|
|
709
|
-
if (errors.length > shown.length) {
|
|
710
|
-
shown.push(`... (${errors.length - shown.length} additional errors omitted from preview)`);
|
|
711
|
-
}
|
|
712
|
-
return shown.join("\n");
|
|
713
|
-
}
|
|
714
|
-
function formatDashboardText(data) {
|
|
715
|
-
const lines = [];
|
|
716
|
-
if (typeof data.port === "number")
|
|
717
|
-
lines.push(`Port: ${data.port}`);
|
|
718
|
-
if (typeof data.pid === "number")
|
|
719
|
-
lines.push(`PID: ${data.pid}`);
|
|
720
|
-
if (typeof data.stopped === "boolean")
|
|
721
|
-
lines.push(`Stopped: ${data.stopped}`);
|
|
722
|
-
const reason = getStringField(data, "reason");
|
|
723
|
-
if (reason)
|
|
724
|
-
lines.push(`Reason: ${redactModelFacingText(reason)}`);
|
|
725
|
-
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
726
|
-
}
|
|
727
|
-
function formatChatText(data) {
|
|
728
|
-
const response = getStringField(data, "response") ?? getStringField(data, "message") ?? getStringField(data, "text") ?? getStringField(data, "result");
|
|
729
|
-
if (response)
|
|
730
|
-
return redactModelFacingText(response);
|
|
731
|
-
const model = getStringField(data, "model");
|
|
732
|
-
const provider = getStringField(data, "provider");
|
|
733
|
-
const lines = [model ? `Model: ${redactModelFacingText(model)}` : undefined, provider ? `Provider: ${redactModelFacingText(provider)}` : undefined].filter(Boolean);
|
|
734
|
-
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
735
|
-
}
|
|
736
|
-
function formatDoctorText(data) {
|
|
737
|
-
const lines = [];
|
|
738
|
-
const status = getStringField(data, "status") ?? getStringField(data, "result");
|
|
739
|
-
if (status)
|
|
740
|
-
lines.push(`Status: ${redactModelFacingText(status)}`);
|
|
741
|
-
const summary = isRecord(data.summary) ? data.summary : undefined;
|
|
742
|
-
if (summary) {
|
|
743
|
-
const parts = ["pass", "warn", "fail"].flatMap((key) => typeof summary[key] === "number" ? [`${key}:${summary[key]}`] : []);
|
|
744
|
-
if (parts.length > 0)
|
|
745
|
-
lines.push(`Summary: ${parts.join(", ")}`);
|
|
746
|
-
}
|
|
747
|
-
const checks = getArrayField(data, "checks");
|
|
748
|
-
if (checks) {
|
|
749
|
-
lines.push(`Checks: ${checks.length}`);
|
|
750
|
-
for (const [index, item] of checks.slice(0, 30).entries()) {
|
|
751
|
-
if (!isRecord(item)) {
|
|
752
|
-
lines.push(`${index + 1}. ${stringifyModelFacing(item)}`);
|
|
753
|
-
continue;
|
|
754
|
-
}
|
|
755
|
-
const checkStatus = getStringField(item, "status") ?? "info";
|
|
756
|
-
const id = getStringField(item, "id");
|
|
757
|
-
const category = getStringField(item, "category");
|
|
758
|
-
const message = getStringField(item, "message") ?? getStringField(item, "name") ?? getStringField(item, "title") ?? getStringField(item, "check") ?? stringifyModelFacing(item);
|
|
759
|
-
const label = [category, id].filter(Boolean).join("/");
|
|
760
|
-
lines.push(`${index + 1}. [${redactModelFacingText(checkStatus)}]${label ? ` ${redactModelFacingText(label)}:` : ""} ${firstLine(redactModelFacingText(message), 220)}`);
|
|
761
|
-
const fix = getStringField(item, "fix");
|
|
762
|
-
if (fix)
|
|
763
|
-
lines.push(` fix: ${redactModelFacingText(fix)}`);
|
|
764
|
-
}
|
|
765
|
-
if (checks.length > 30)
|
|
766
|
-
lines.push(`... (${checks.length - 30} additional checks omitted from preview)`);
|
|
767
|
-
}
|
|
768
|
-
for (const key of ["issues", "problems"]) {
|
|
769
|
-
const items = getArrayField(data, key);
|
|
770
|
-
if (items)
|
|
771
|
-
lines.push(`${key}: ${items.length}`);
|
|
772
|
-
}
|
|
773
|
-
if (lines.length === 0) {
|
|
774
|
-
const keys = Object.keys(data).filter((key) => key !== "success");
|
|
775
|
-
if (keys.length > 0)
|
|
776
|
-
return `Doctor diagnostics returned unrecognized fields: ${keys.map(redactModelFacingText).join(", ")}. See details.data for structured diagnostics.`;
|
|
777
|
-
}
|
|
778
|
-
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
779
|
-
}
|
|
780
|
-
function formatCookieRecordText(item, fallbackName) {
|
|
781
|
-
const name = redactModelFacingText(getStringField(item, "name") ?? fallbackName);
|
|
782
|
-
const domain = getStringField(item, "domain");
|
|
783
|
-
const path = getStringField(item, "path");
|
|
784
|
-
const flags = [item.httpOnly === true ? "httpOnly" : undefined, item.secure === true ? "secure" : undefined].filter(Boolean).join(", ");
|
|
785
|
-
const location = [domain, path].filter(Boolean).join("");
|
|
786
|
-
return [name, location ? `(${redactModelFacingText(location)})` : undefined, flags ? `[${flags}]` : undefined].filter(Boolean).join(" ");
|
|
787
|
-
}
|
|
788
|
-
function formatCookiesText(data) {
|
|
789
|
-
const cookies = getArrayField(data, "cookies");
|
|
790
|
-
if (cookies) {
|
|
791
|
-
if (cookies.length === 0)
|
|
792
|
-
return "No cookies.";
|
|
793
|
-
return cookies
|
|
794
|
-
.map((item, index) => (isRecord(item) ? formatCookieRecordText(item, `(cookie ${index + 1})`) : `${index + 1}. [REDACTED]`))
|
|
795
|
-
.join("\n");
|
|
796
|
-
}
|
|
797
|
-
if (getStringField(data, "name") || getStringField(data, "domain") || getStringField(data, "path") || Object.hasOwn(data, "value")) {
|
|
798
|
-
return formatCookieRecordText(data, "cookie");
|
|
799
|
-
}
|
|
800
|
-
if (data.set === true)
|
|
801
|
-
return "Cookie set.";
|
|
802
|
-
if (data.cleared === true || data.clear === true)
|
|
803
|
-
return "Cookies cleared.";
|
|
804
|
-
return undefined;
|
|
805
|
-
}
|
|
806
|
-
function valueContainsStorageSecret(value) {
|
|
807
|
-
if (typeof value === "string") {
|
|
808
|
-
const trimmed = value.trim();
|
|
809
|
-
if (trimmed.length === 0)
|
|
810
|
-
return false;
|
|
811
|
-
if (STORAGE_TOKEN_VALUE_PATTERN.test(trimmed) || STORAGE_SECRET_VALUE_WORD_PATTERN.test(trimmed) || STORAGE_EMAIL_VALUE_PATTERN.test(trimmed) || STORAGE_IDENTITY_VALUE_PATTERN.test(trimmed))
|
|
812
|
-
return true;
|
|
813
|
-
try {
|
|
814
|
-
const url = new URL(trimmed);
|
|
815
|
-
if (url.protocol === "http:" || url.protocol === "https:" || url.username || url.password || url.search)
|
|
816
|
-
return true;
|
|
817
|
-
}
|
|
818
|
-
catch { }
|
|
819
|
-
if (redactSensitiveText(trimmed) !== trimmed)
|
|
820
|
-
return true;
|
|
821
|
-
try {
|
|
822
|
-
return valueContainsStorageSecret(JSON.parse(trimmed));
|
|
823
|
-
}
|
|
824
|
-
catch {
|
|
825
|
-
return false;
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
if (Array.isArray(value))
|
|
829
|
-
return value.some((item) => valueContainsStorageSecret(item));
|
|
830
|
-
if (!isRecord(value))
|
|
831
|
-
return false;
|
|
832
|
-
return Object.entries(value).some(([key, entryValue]) => STORAGE_SECRET_KEY_PATTERN.test(key) || valueContainsStorageSecret(entryValue));
|
|
833
|
-
}
|
|
834
|
-
function shouldRevealStorageValue(key, value) {
|
|
835
|
-
if (!key || STORAGE_SECRET_KEY_PATTERN.test(key) || !STORAGE_BENIGN_KEY_PATTERN.test(key))
|
|
836
|
-
return false;
|
|
837
|
-
if (valueContainsStorageSecret(value))
|
|
838
|
-
return false;
|
|
839
|
-
if (typeof value === "string")
|
|
840
|
-
return value.length <= STORAGE_VALUE_PREVIEW_MAX_CHARS;
|
|
841
|
-
return value === null || typeof value === "number" || typeof value === "boolean";
|
|
842
|
-
}
|
|
843
|
-
function formatStorageValue(key, value) {
|
|
844
|
-
if (!shouldRevealStorageValue(key, value))
|
|
845
|
-
return "[REDACTED]";
|
|
846
|
-
if (typeof value === "string")
|
|
847
|
-
return redactModelFacingText(value);
|
|
848
|
-
return stringifyModelFacing(value);
|
|
849
|
-
}
|
|
850
|
-
function redactStorageEntryValue(item) {
|
|
851
|
-
if (!Object.hasOwn(item, "value"))
|
|
852
|
-
return redactSensitiveValue(item);
|
|
853
|
-
const key = getStringField(item, "key") ?? getStringField(item, "name");
|
|
854
|
-
const value = item.value;
|
|
855
|
-
if (shouldRevealStorageValue(key, value))
|
|
856
|
-
return redactSensitiveValue(item);
|
|
857
|
-
return {
|
|
858
|
-
...redactSensitiveValue({ ...item, value: undefined }),
|
|
859
|
-
value: "[REDACTED]",
|
|
860
|
-
valueRedacted: true,
|
|
861
|
-
valueRedactionReason: key && STORAGE_SECRET_KEY_PATTERN.test(key) ? "sensitive-key" : "sensitive-value",
|
|
862
|
-
};
|
|
863
|
-
}
|
|
864
|
-
function redactStorageData(value) {
|
|
865
|
-
if (Array.isArray(value))
|
|
866
|
-
return value.map((item) => redactStorageData(item));
|
|
867
|
-
if (!isRecord(value))
|
|
868
|
-
return redactSensitiveValue(value);
|
|
869
|
-
const entries = Object.fromEntries(Object.entries(value).map(([key, entryValue]) => {
|
|
870
|
-
if (key === "data" && isRecord(entryValue))
|
|
871
|
-
return [key, Object.fromEntries(Object.entries(entryValue).map(([storageKey, storageValue]) => [storageKey, shouldRevealStorageValue(storageKey, storageValue) ? redactSensitiveValue(storageValue) : "[REDACTED]"]))];
|
|
872
|
-
if ((key === "entries" || key === "items") && Array.isArray(entryValue))
|
|
873
|
-
return [key, entryValue.map((item) => isRecord(item) ? redactStorageEntryValue(item) : redactSensitiveValue(item))];
|
|
874
|
-
if (key === "value") {
|
|
875
|
-
const itemKey = getStringField(value, "key") ?? getStringField(value, "name");
|
|
876
|
-
return [key, shouldRevealStorageValue(itemKey, entryValue) ? redactSensitiveValue(entryValue) : "[REDACTED]"];
|
|
877
|
-
}
|
|
878
|
-
return [key, redactSensitiveValue(entryValue)];
|
|
879
|
-
}));
|
|
880
|
-
if (Object.hasOwn(value, "value")) {
|
|
881
|
-
const key = getStringField(value, "key") ?? getStringField(value, "name");
|
|
882
|
-
if (!shouldRevealStorageValue(key, value.value)) {
|
|
883
|
-
entries.valueRedacted = true;
|
|
884
|
-
entries.valueRedactionReason = key && STORAGE_SECRET_KEY_PATTERN.test(key) ? "sensitive-key" : "sensitive-value";
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
return entries;
|
|
888
|
-
}
|
|
889
|
-
function formatStorageText(data) {
|
|
890
|
-
const type = getStringField(data, "type") ?? getStringField(data, "storage") ?? "storage";
|
|
891
|
-
if (isRecord(data.data)) {
|
|
892
|
-
return Object.entries(data.data).map(([key, value]) => `${redactModelFacingText(key)}: ${formatStorageValue(key, value)}`).join("\n") || `${type}: no entries.`;
|
|
893
|
-
}
|
|
894
|
-
const entries = getArrayField(data, "entries") ?? getArrayField(data, "items");
|
|
895
|
-
if (entries) {
|
|
896
|
-
if (entries.length === 0)
|
|
897
|
-
return `${type}: no entries.`;
|
|
898
|
-
return entries
|
|
899
|
-
.map((item, index) => {
|
|
900
|
-
if (!isRecord(item))
|
|
901
|
-
return `${index + 1}. [REDACTED]`;
|
|
902
|
-
const rawKey = getStringField(item, "key") ?? getStringField(item, "name") ?? `(entry ${index + 1})`;
|
|
903
|
-
const key = redactModelFacingText(rawKey);
|
|
904
|
-
return Object.hasOwn(item, "value") ? `${key}: ${formatStorageValue(rawKey, item.value)}` : key;
|
|
905
|
-
})
|
|
906
|
-
.join("\n");
|
|
907
|
-
}
|
|
908
|
-
const key = getStringField(data, "key");
|
|
909
|
-
if (key && Object.hasOwn(data, "value"))
|
|
910
|
-
return `${type} ${redactModelFacingText(key)}: ${formatStorageValue(key, data.value)}`;
|
|
911
|
-
if (key && data.set === true)
|
|
912
|
-
return `${type} set: ${redactModelFacingText(key)}`;
|
|
913
|
-
if (data.cleared === true || data.clear === true)
|
|
914
|
-
return `${type} cleared.`;
|
|
915
|
-
return undefined;
|
|
1
|
+
import { redactSensitiveText } from "../../runtime.js";
|
|
2
|
+
import { getArrayField, getStringField, redactModelFacingText, stringifyModelFacing, } from "./common.js";
|
|
3
|
+
import { formatA11yText } from "./diagnostic-a11y.js";
|
|
4
|
+
import { formatDashboardText, formatDoctorText } from "./diagnostic-health.js";
|
|
5
|
+
import { formatAuthShowText, formatProfilesText, formatSessionText, formatStateText, } from "./diagnostic-identity.js";
|
|
6
|
+
import { formatConsoleText, formatErrorsText } from "./diagnostic-logs.js";
|
|
7
|
+
import { formatNetworkRequestText, formatNetworkRequestsText } from "./diagnostic-network.js";
|
|
8
|
+
import { formatCookiesText, formatStorageText } from "./diagnostic-storage.js";
|
|
9
|
+
import { getStreamSummary } from "./diagnostic-stream.js";
|
|
10
|
+
export { getTabSummary, formatProfilesText } from "./diagnostic-identity.js";
|
|
11
|
+
export { buildNetworkRequestsNextActions, formatNetworkRouteDiagnosticsText, } from "./diagnostic-network-actions.js";
|
|
12
|
+
export { redactPresentationData } from "./diagnostic-redaction.js";
|
|
13
|
+
export { buildStreamNextActions, enrichStreamStatusData, getStreamSummary, } from "./diagnostic-stream.js";
|
|
14
|
+
export { formatDiagnosticSummary } from "./diagnostic-summary.js";
|
|
15
|
+
function formatProfileCommand(command, data) {
|
|
16
|
+
const profiles = getArrayField(data, "profiles");
|
|
17
|
+
if (profiles) {
|
|
18
|
+
return formatProfilesText(profiles, command.command === "profiles" ? "Chrome profiles" : "auth profiles");
|
|
19
|
+
}
|
|
20
|
+
return command.command === "auth" && command.subcommand === "show"
|
|
21
|
+
? formatAuthShowText(data)
|
|
22
|
+
: undefined;
|
|
916
23
|
}
|
|
917
24
|
function formatDialogText(data) {
|
|
918
25
|
const lines = [];
|
|
919
|
-
if (typeof data.open === "boolean")
|
|
26
|
+
if (typeof data.open === "boolean") {
|
|
920
27
|
lines.push(data.open ? "Dialog open." : "No dialog open.");
|
|
28
|
+
}
|
|
921
29
|
const type = getStringField(data, "type");
|
|
922
|
-
if (type)
|
|
30
|
+
if (type !== undefined) {
|
|
923
31
|
lines.push(`Type: ${redactModelFacingText(type)}`);
|
|
32
|
+
}
|
|
924
33
|
const message = getStringField(data, "message");
|
|
925
|
-
if (message)
|
|
34
|
+
if (message !== undefined) {
|
|
926
35
|
lines.push(`Message: ${redactModelFacingText(message)}`);
|
|
927
|
-
|
|
36
|
+
}
|
|
37
|
+
if (data.accepted === true) {
|
|
928
38
|
lines.push("Accepted.");
|
|
929
|
-
|
|
39
|
+
}
|
|
40
|
+
if (data.dismissed === true) {
|
|
930
41
|
lines.push("Dismissed.");
|
|
42
|
+
}
|
|
931
43
|
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
932
44
|
}
|
|
933
45
|
function formatFrameText(data) {
|
|
934
|
-
const frame = getStringField(data, "frame") ??
|
|
46
|
+
const frame = getStringField(data, "frame") ??
|
|
47
|
+
getStringField(data, "name") ??
|
|
48
|
+
getStringField(data, "selector");
|
|
935
49
|
const url = getStringField(data, "url");
|
|
936
50
|
const title = getStringField(data, "title");
|
|
937
|
-
const lines = [
|
|
51
|
+
const lines = [
|
|
52
|
+
frame === undefined ? undefined : `Frame: ${redactModelFacingText(frame)}`,
|
|
53
|
+
title === undefined ? undefined : `Title: ${redactModelFacingText(title)}`,
|
|
54
|
+
url === undefined ? undefined : `URL: ${redactSensitiveText(url)}`,
|
|
55
|
+
].filter(Boolean);
|
|
938
56
|
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
939
57
|
}
|
|
940
|
-
function
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
if (typeof data.encrypted === "boolean")
|
|
948
|
-
lines.push(`Encrypted: ${data.encrypted ? "yes" : "no"}`);
|
|
949
|
-
if (typeof data.size === "number")
|
|
950
|
-
lines.push(`Size: ${data.size} bytes`);
|
|
951
|
-
return lines.join("\n");
|
|
952
|
-
}
|
|
953
|
-
const states = getArrayField(data, "states") ?? getArrayField(data, "files");
|
|
954
|
-
if (states) {
|
|
955
|
-
if (states.length === 0)
|
|
956
|
-
return "No saved states.";
|
|
957
|
-
return states
|
|
958
|
-
.map((item, index) => {
|
|
959
|
-
if (!isRecord(item))
|
|
960
|
-
return `${index + 1}. ${stringifyModelFacing(item)}`;
|
|
961
|
-
const name = getStringField(item, "name") ?? getStringField(item, "file") ?? getStringField(item, "path") ?? `(state ${index + 1})`;
|
|
962
|
-
const url = getStringField(item, "url");
|
|
963
|
-
return url ? `${index + 1}. ${redactModelFacingText(name)} — ${redactSensitiveText(url)}` : `${index + 1}. ${redactModelFacingText(name)}`;
|
|
964
|
-
})
|
|
965
|
-
.join("\n");
|
|
966
|
-
}
|
|
967
|
-
if (data.loaded === true)
|
|
968
|
-
return `State loaded: ${redactModelFacingText(getStringField(data, "path") ?? getStringField(data, "name") ?? "ok")}`;
|
|
969
|
-
if (data.cleared === true || data.clear === true)
|
|
970
|
-
return "State cleared.";
|
|
971
|
-
return undefined;
|
|
972
|
-
}
|
|
973
|
-
function redactStatefulValues(value, sensitiveKeys) {
|
|
974
|
-
if (Array.isArray(value))
|
|
975
|
-
return value.map((item) => redactStatefulValues(item, sensitiveKeys));
|
|
976
|
-
if (!isRecord(value))
|
|
977
|
-
return redactSensitiveValue(value);
|
|
978
|
-
return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => [
|
|
979
|
-
key,
|
|
980
|
-
sensitiveKeys.has(key.toLowerCase()) ? "[REDACTED]" : redactStatefulValues(entryValue, sensitiveKeys),
|
|
981
|
-
]));
|
|
982
|
-
}
|
|
983
|
-
function redactNativeContextText(commandInfo, text, stdin) {
|
|
984
|
-
if (commandInfo.command === "batch") {
|
|
985
|
-
const steps = getUpstreamEffectiveBatchSteps(commandInfo.commandTokens ?? ["batch"], stdin);
|
|
986
|
-
if (steps.some(step => step[0] === "cookies"))
|
|
987
|
-
text = redactNativeContextText({ command: "cookies" }, text);
|
|
988
|
-
if (steps.some(step => step[0] === "storage"))
|
|
989
|
-
text = redactNativeContextText({ command: "storage" }, text);
|
|
990
|
-
return text;
|
|
991
|
-
}
|
|
992
|
-
if (commandInfo.command === "cookies")
|
|
993
|
-
return text.replace(/^([^=\r\n]*)=([^\r\n]*)/gm, "$1=[REDACTED]");
|
|
994
|
-
if (commandInfo.command !== "storage")
|
|
995
|
-
return text;
|
|
996
|
-
const tokens = commandInfo.commandTokens;
|
|
997
|
-
const operation = tokens?.[2];
|
|
998
|
-
const key = operation === "get" ? tokens?.[3] : operation === "set" || operation === "clear" ? undefined : operation;
|
|
999
|
-
if (key !== undefined && text.startsWith(`${key}: `)) {
|
|
1000
|
-
const suffix = text.endsWith("\n") ? "\n" : "";
|
|
1001
|
-
const value = text.slice(key.length + 2, suffix ? -1 : undefined);
|
|
1002
|
-
return `${key}: ${formatStorageValue(key, value)}${suffix}`;
|
|
58
|
+
function formatChatText(data) {
|
|
59
|
+
const response = getStringField(data, "response") ??
|
|
60
|
+
getStringField(data, "message") ??
|
|
61
|
+
getStringField(data, "text") ??
|
|
62
|
+
getStringField(data, "result");
|
|
63
|
+
if (response !== undefined) {
|
|
64
|
+
return redactModelFacingText(response);
|
|
1003
65
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
if (commandInfo.command === "cookies")
|
|
1012
|
-
return redactStatefulValues(data, new Set(["value"]));
|
|
1013
|
-
if (commandInfo.command === "storage")
|
|
1014
|
-
return redactStorageData(data);
|
|
1015
|
-
if (commandInfo.command === "state" && commandInfo.subcommand === "show")
|
|
1016
|
-
return redactStatefulValues(data, new Set(["value"]));
|
|
1017
|
-
return redactSensitiveValue(data);
|
|
66
|
+
const model = getStringField(data, "model");
|
|
67
|
+
const provider = getStringField(data, "provider");
|
|
68
|
+
const lines = [
|
|
69
|
+
model === undefined ? undefined : `Model: ${redactModelFacingText(model)}`,
|
|
70
|
+
provider === undefined ? undefined : `Provider: ${redactModelFacingText(provider)}`,
|
|
71
|
+
].filter(Boolean);
|
|
72
|
+
return lines.length > 0 ? lines.join("\n") : undefined;
|
|
1018
73
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
return
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
return
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
74
|
+
function formatClipboardText(data) {
|
|
75
|
+
const text = getStringField(data, "text") ?? getStringField(data, "value") ?? getStringField(data, "result");
|
|
76
|
+
return text === undefined ? undefined : redactModelFacingText(text);
|
|
77
|
+
}
|
|
78
|
+
function formatNetworkText(command, data) {
|
|
79
|
+
if (command.subcommand === "requests") {
|
|
80
|
+
return formatNetworkRequestsText(data, command);
|
|
81
|
+
}
|
|
82
|
+
return command.subcommand === "request" ? formatNetworkRequestText(data) : undefined;
|
|
83
|
+
}
|
|
84
|
+
export function formatDiagnosticText(command, data) {
|
|
85
|
+
switch (command.command ?? "") {
|
|
86
|
+
case "session":
|
|
87
|
+
return formatSessionText(data);
|
|
88
|
+
case "profiles":
|
|
89
|
+
case "auth":
|
|
90
|
+
return formatProfileCommand(command, data);
|
|
91
|
+
case "cookies":
|
|
92
|
+
return formatCookiesText(data);
|
|
93
|
+
case "storage":
|
|
94
|
+
return formatStorageText(data);
|
|
95
|
+
case "dialog":
|
|
96
|
+
return formatDialogText(data);
|
|
97
|
+
case "frame":
|
|
98
|
+
return formatFrameText(data);
|
|
99
|
+
case "state":
|
|
100
|
+
return formatStateText(data, command.subcommand);
|
|
101
|
+
case "network":
|
|
102
|
+
return formatNetworkText(command, data);
|
|
103
|
+
case "diff":
|
|
104
|
+
return stringifyModelFacing(data);
|
|
105
|
+
case "clipboard":
|
|
106
|
+
return formatClipboardText(data);
|
|
107
|
+
case "stream":
|
|
108
|
+
return getStreamSummary(data);
|
|
109
|
+
case "chat":
|
|
110
|
+
return formatChatText(data);
|
|
111
|
+
case "console":
|
|
112
|
+
return formatConsoleText(data, command);
|
|
113
|
+
case "errors":
|
|
114
|
+
return formatErrorsText(data, command);
|
|
115
|
+
case "a11y":
|
|
116
|
+
return formatA11yText(data);
|
|
117
|
+
case "dashboard":
|
|
118
|
+
return formatDashboardText(data);
|
|
119
|
+
case "doctor":
|
|
120
|
+
return formatDoctorText(data);
|
|
121
|
+
default:
|
|
122
|
+
return undefined;
|
|
1059
123
|
}
|
|
1060
|
-
if (commandInfo.command === "chat")
|
|
1061
|
-
return formatChatText(data);
|
|
1062
|
-
if (commandInfo.command === "console")
|
|
1063
|
-
return formatConsoleText(data, commandInfo);
|
|
1064
|
-
if (commandInfo.command === "errors")
|
|
1065
|
-
return formatErrorsText(data, commandInfo);
|
|
1066
|
-
if (commandInfo.command === "a11y")
|
|
1067
|
-
return formatA11yText(data);
|
|
1068
|
-
if (commandInfo.command === "dashboard")
|
|
1069
|
-
return formatDashboardText(data);
|
|
1070
|
-
if (commandInfo.command === "doctor")
|
|
1071
|
-
return formatDoctorText(data);
|
|
1072
|
-
return undefined;
|
|
1073
124
|
}
|