pi-agent-browser-native 0.9.3 → 0.9.5
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 +106 -5
- package/README.md +58 -791
- package/dist/extensions/agent-browser/index.js +43101 -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 +231 -0
- package/dist/extensions/agent-browser/lib/config.js +20 -8
- package/dist/extensions/agent-browser/lib/electron/cdp.js +20 -8
- package/dist/extensions/agent-browser/lib/electron/cleanup.js +128 -83
- 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 +90 -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 +261 -355
- 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/fs-utils.js +1 -9
- package/dist/extensions/agent-browser/lib/input-modes/electron.js +162 -121
- package/dist/extensions/agent-browser/lib/input-modes/job.js +123 -317
- package/dist/extensions/agent-browser/lib/input-modes/lookup-network-evidence.js +116 -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 +58 -412
- package/dist/extensions/agent-browser/lib/input-modes/params.js +86 -40
- 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 +203 -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 +187 -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 +147 -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 +212 -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 +169 -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 +93 -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 +68 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-data.js +169 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-presentation.js +182 -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 +167 -0
- package/dist/extensions/agent-browser/lib/orchestration/execution-queue.js +22 -10
- 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 +109 -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 +81 -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 +211 -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 +193 -0
- package/dist/extensions/agent-browser/lib/web-search-request.js +102 -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 +124 -614
- 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 +19 -6
- package/docs/CODE_QUALITY.md +267 -0
- package/docs/COMMAND_REFERENCE.md +272 -241
- package/docs/ELECTRON.md +77 -46
- package/docs/REFERENCE.md +869 -0
- package/docs/RELEASE.md +25 -22
- package/docs/REQUIREMENTS.md +2 -1
- package/docs/SUPPORT_MATRIX.md +81 -79
- package/docs/TOOL_CONTRACT.md +158 -125
- package/docs/platform-smoke.md +8 -8
- package/package.json +144 -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 +235 -132
- package/scripts/convert-browser-session.mjs +30 -9
- package/scripts/doctor-sources.mjs +195 -0
- package/scripts/doctor.mjs +94 -249
- 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 +132 -0
- package/scripts/platform-smoke/linux-image/Dockerfile +8 -2
- package/scripts/platform-smoke/suite-checks.mjs +98 -0
- package/scripts/platform-smoke/suite-evidence.mjs +281 -0
- package/scripts/platform-smoke/targets.mjs +154 -472
- package/scripts/platform-smoke.mjs +55 -40
- package/scripts/prepare.mjs +16 -7
|
@@ -1,975 +1,25 @@
|
|
|
1
1
|
import { rm } from "node:fs/promises";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { OPEN_RESULT_TAB_CORRECTION_FLAGS } from "../../launch-scoped-flags.js";
|
|
9
|
-
import { cleanupElectronLaunchResources, inspectElectronLaunchStatus } from "../../electron/cleanup.js";
|
|
10
|
-
import { getResultingPageTargetState, commandRequiresLivePageVerification } from "../../page-target-validation.js";
|
|
11
|
-
import { analyzeNetworkSourceLookupResults, analyzeSourceLookupResults, redactNetworkSourceLookupAnalysis } from "../../input-modes/lookups.js";
|
|
12
|
-
import { analyzeQaPresetResults, analyzeQaPresetTimeout, buildQaCompactFailureText, buildQaCompactPassText, extractQaPageContext } from "../../input-modes/job.js";
|
|
13
|
-
import { applyNetworkRouteRecords, buildNetworkRouteDiagnostics } from "../../results/network-routes.js";
|
|
14
|
-
import { buildToolPresentation } from "../../results/presentation.js";
|
|
15
|
-
import { compactLargePresentationOutput } from "../../results/presentation/large-output.js";
|
|
16
|
-
import { extractEnvelopeErrorText, getAgentBrowserErrorText, parseAgentBrowserEnvelope } from "../../results/envelope.js";
|
|
17
|
-
import { detectConfirmationRequired } from "../../results/confirmation.js";
|
|
18
|
-
import { extractAgentBrowserLifecycle, omitUpstreamLifecycle } from "../../results/presentation/common.js";
|
|
19
|
-
import { getClipboardWritePayloadCandidates, redactClipboardPermissionEcho, redactClipboardPermissionErrorValue } from "../../results/presentation/errors.js";
|
|
20
|
-
import { shouldCaptureSemanticActionNavigationSummary } from "../../results/presentation/semantic-action.js";
|
|
21
|
-
import { buildPageTransitionRefSnapshotInvalidation, commandExplicitlyTargetsAboutBlank, getCommandRefSnapshotInvalidation, deriveSessionTabTarget, extractLatestRefSnapshotStateFromBatchResults, extractRefSnapshotFromData, extractSessionTabTargetFromBatchResults, extractSessionTabTargetFromCommandData, isAboutBlankSessionTabTarget, normalizeSessionTabTarget, } from "../../session-page-state.js";
|
|
22
|
-
import { isRecord } from "../../parsing.js";
|
|
23
|
-
import { getAgentBrowserProcessEnvironment } from "../../process-environment.js";
|
|
24
|
-
import { buildReadConfirmationNextActions, isBrowserIndependentConfirmation, isSuccessfulNativeConfirmedClose, nextReadConfirmation, parseReadConfirmation } from "../../read-confirmation.js";
|
|
25
|
-
import { pruneOwnedManagedSessionRestoreSnapshots } from "../../managed-session-restore.js";
|
|
26
|
-
import { isManagedSessionRestoreKey } from "../../managed-session-storage.js";
|
|
27
|
-
import { createFreshSessionName, extractUpstreamCommandTokens, redactInvocationArgs, resolveManagedSessionState } from "../../runtime.js";
|
|
28
|
-
import { getUpstreamEffectiveBatchSteps } from "../batch-stdin.js";
|
|
29
|
-
import { closeManagedSession, inspectManagedSessionDaemon } from "./managed-session-daemon-policy.js";
|
|
30
|
-
import { applyOpenResultTabCorrection, applyBrowserRunStatePatch, buildAboutBlankRecoveryHint, buildAboutBlankWarning, buildElectronPostCommandHealthDiagnostic, buildElectronRefFreshnessDiagnostic, buildElectronSessionMismatch, buildManagedSessionOutcome, collectOpenResultTabCorrection, collectSessionTabSelection, collectSessionTabTarget, commandChoosesSessionTabTarget, extractNavigationSummaryFromData, extractStringResultField, findElectronLaunchRecordForSession, formatElectronPostCommandHealthText, formatElectronSessionMismatchText, getSessionContextKey, getStaleRefArgs, mergeNavigationSummaryIntoData, runSessionCommandData, shouldCaptureNavigationSummary, shouldCorrectSessionTabAfterCommand, shouldInspectElectronPostCommandHealth, updateTraceOwnerState, } from "./session-state.js";
|
|
31
|
-
import { collectClickDispatchDiagnostic } from "./click-dispatch.js";
|
|
32
|
-
import { buildScrollNoopDiagnostic, collectComboboxFocusDiagnostic, collectElectronBroadGetTextScopeDiagnostics, collectElectronHandoff, collectFillVerificationDiagnostic, collectNavigationSummary, collectOverlayBlockerDiagnostic, collectQaAttachedTarget, collectSnapshotOverlayBlockerDiagnostic, collectRecordingDependencyWarning, collectScrollPositionSnapshot, collectSelectorTextVisibilityDiagnostics, collectTimeoutPartialProgress, sleepMs, formatQaAttachedTargetText, getArtifactCleanupGuidance, getEvalResultWarning, getEvalStdinHint, getSourceLookupElectronContext, } from "./diagnostics.js";
|
|
33
|
-
import { repairScreenshotData } from "./prepare.js";
|
|
34
|
-
import { mergeRecordingRecoveryPresentation, recoverRecordingStop } from "./recording-recovery.js";
|
|
35
|
-
import { getPersistentSessionArtifactStore } from "./session-state.js";
|
|
36
|
-
import { nativePolicyDefinitelyUnestablished } from "./session-state.js";
|
|
37
|
-
import { buildFinalAgentBrowserToolResult, buildRedactedPresentationContent, buildWrapperRecoveryHint, prepareFinalResultRecoveryState, redactExactSensitiveValue, } from "./final-result.js";
|
|
38
|
-
async function repairScreenshotArtifact(options) {
|
|
39
|
-
const { cwd, envelope, request } = options;
|
|
40
|
-
if (!request || !envelope || !isRecord(envelope.data))
|
|
41
|
-
return { envelope, request };
|
|
42
|
-
const repaired = await repairScreenshotData({ cwd, data: envelope.data, request });
|
|
43
|
-
return { envelope: { ...envelope, data: repaired.data }, request: repaired.request };
|
|
44
|
-
}
|
|
45
|
-
async function repairBatchScreenshotArtifacts(options) {
|
|
46
|
-
const { cwd, envelope, requests } = options;
|
|
47
|
-
if (!envelope || !Array.isArray(envelope.data) || !requests?.some((request) => request !== undefined))
|
|
48
|
-
return { envelope, requests };
|
|
49
|
-
const repairedRequests = [];
|
|
50
|
-
const repairedData = await Promise.all(envelope.data.map(async (item, index) => {
|
|
51
|
-
const request = requests[index];
|
|
52
|
-
if (!request || !isRecord(item) || !isRecord(item.result))
|
|
53
|
-
return item;
|
|
54
|
-
const repaired = await repairScreenshotData({ cwd, data: item.result, request });
|
|
55
|
-
repairedRequests[index] = repaired.request;
|
|
56
|
-
return { ...item, result: repaired.data };
|
|
57
|
-
}));
|
|
58
|
-
return { envelope: { ...envelope, data: repairedData }, requests: repairedRequests };
|
|
59
|
-
}
|
|
60
|
-
function getEnvelopeErrorString(envelope) {
|
|
61
|
-
if (!envelope?.error)
|
|
62
|
-
return undefined;
|
|
63
|
-
if (typeof envelope.error === "string")
|
|
64
|
-
return envelope.error;
|
|
65
|
-
if (isRecord(envelope.error) && typeof envelope.error.message === "string")
|
|
66
|
-
return envelope.error.message;
|
|
67
|
-
return String(envelope.error);
|
|
68
|
-
}
|
|
69
|
-
function isStreamEnableAlreadyEnabledNoop(options) {
|
|
70
|
-
if (!options.processSucceeded || options.command !== "stream" || options.subcommand !== "enable" || options.envelope?.success !== false)
|
|
71
|
-
return false;
|
|
72
|
-
const message = (getEnvelopeErrorString(options.envelope) ?? "").trim().replace(/[.!]+$/, "").toLowerCase();
|
|
73
|
-
return message === "streaming is already enabled for this session" || message === "streaming is already enabled" || message === "stream already enabled";
|
|
74
|
-
}
|
|
75
|
-
function isPendingWebMcpMutation(command, subcommand, data) {
|
|
76
|
-
return command === "webmcp"
|
|
77
|
-
&& ["invoke", "result"].includes(subcommand ?? "")
|
|
78
|
-
&& isRecord(data)
|
|
79
|
-
&& data.status === "pending";
|
|
80
|
-
}
|
|
81
|
-
function isWebMcpSettlementCommand(command, subcommand) {
|
|
82
|
-
return command === "webmcp" && ["result", "cancel"].includes(subcommand ?? "");
|
|
83
|
-
}
|
|
84
|
-
function batchHasPendingWebMcpMutation(data) {
|
|
85
|
-
if (!Array.isArray(data))
|
|
86
|
-
return false;
|
|
87
|
-
return data.some((row) => {
|
|
88
|
-
if (!isRecord(row) || row.success === false || !Array.isArray(row.command) || !row.command.every((token) => typeof token === "string"))
|
|
89
|
-
return false;
|
|
90
|
-
const [command, subcommand] = extractUpstreamCommandTokens(row.command);
|
|
91
|
-
return isPendingWebMcpMutation(command, subcommand, row.result);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
function batchHasFailedWebMcpSettlement(data) {
|
|
95
|
-
if (!Array.isArray(data))
|
|
96
|
-
return false;
|
|
97
|
-
return data.some((row) => {
|
|
98
|
-
if (!isRecord(row) || row.success !== false || !Array.isArray(row.command) || !row.command.every((token) => typeof token === "string"))
|
|
99
|
-
return false;
|
|
100
|
-
const [command, subcommand] = extractUpstreamCommandTokens(row.command);
|
|
101
|
-
return isWebMcpSettlementCommand(command, subcommand);
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
function batchStartedManagedBrowser(data) {
|
|
105
|
-
if (!Array.isArray(data))
|
|
106
|
-
return false;
|
|
107
|
-
return data.some((entry) => {
|
|
108
|
-
if (!isRecord(entry) || entry.success !== true || !Array.isArray(entry.command))
|
|
109
|
-
return false;
|
|
110
|
-
const command = typeof entry.command[0] === "string" ? entry.command[0] : undefined;
|
|
111
|
-
return command === "connect" || command === "goto" || command === "navigate" || isOpenNavigationCommand(command);
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
function withoutNamespaceEntries(entries, namespace) {
|
|
115
|
-
return new Map([...entries].filter(([key]) => !isAgentBrowserSessionIdentityKeyInNamespace(key, namespace)));
|
|
116
|
-
}
|
|
117
|
-
function setNetworkRouteState(options) {
|
|
118
|
-
if (!options.sessionName)
|
|
119
|
-
return options.routesBySession;
|
|
120
|
-
const previousRoutes = options.routesBySession.get(options.sessionName);
|
|
121
|
-
if (options.routes === previousRoutes)
|
|
122
|
-
return options.routesBySession;
|
|
123
|
-
const next = new Map(options.routesBySession);
|
|
124
|
-
if (options.routes && options.routes.length > 0)
|
|
125
|
-
next.set(options.sessionName, options.routes);
|
|
126
|
-
else
|
|
127
|
-
next.delete(options.sessionName);
|
|
128
|
-
return next;
|
|
129
|
-
}
|
|
130
|
-
function applyNetworkRouteState(options) {
|
|
131
|
-
const routes = options.sessionName ? applyNetworkRouteRecords(options.routesBySession.get(options.sessionName), options.commandTokens, options.succeeded) : undefined;
|
|
132
|
-
return setNetworkRouteState({ routes, routesBySession: options.routesBySession, sessionName: options.sessionName });
|
|
133
|
-
}
|
|
134
|
-
function applyBatchNetworkRouteState(options) {
|
|
135
|
-
if (!options.succeeded || !options.sessionName || !Array.isArray(options.data))
|
|
136
|
-
return options.routesBySession;
|
|
137
|
-
let routes = options.routesBySession.get(options.sessionName);
|
|
138
|
-
for (const item of options.data) {
|
|
139
|
-
if (!isRecord(item) || !Array.isArray(item.command) || !item.command.every((token) => typeof token === "string"))
|
|
140
|
-
continue;
|
|
141
|
-
const commandTokens = extractUpstreamCommandTokens(item.command);
|
|
142
|
-
const stepSucceeded = item.success !== false && !detectConfirmationRequired(item.result);
|
|
143
|
-
if (stepSucceeded && isCloseCommand(commandTokens[0]))
|
|
144
|
-
routes = undefined;
|
|
145
|
-
else
|
|
146
|
-
routes = applyNetworkRouteRecords(routes, commandTokens, stepSucceeded);
|
|
147
|
-
}
|
|
148
|
-
return setNetworkRouteState({ routes, routesBySession: options.routesBySession, sessionName: options.sessionName });
|
|
149
|
-
}
|
|
2
|
+
import { captureBrowserOutputOwnership } from "./process-output-ownership.js";
|
|
3
|
+
import { observeNativeEffects } from "./process-output-native-phase.js";
|
|
4
|
+
import { observePageEffects } from "./process-output-page-phase.js";
|
|
5
|
+
import { commitLifecycleEffects } from "./process-output-lifecycle-phase.js";
|
|
6
|
+
import { publishOutputEffects } from "./process-output-publication-phase.js";
|
|
7
|
+
import { buildOutputResult } from "./process-output-publication.js";
|
|
150
8
|
export async function processBrowserOutput(input) {
|
|
151
|
-
const
|
|
152
|
-
const operationCwd = input.operationCwd ?? cwd;
|
|
153
|
-
const { prepared, processResult } = input;
|
|
154
|
-
const { electronChildProcesses, electronLaunchRecords, sessionPageState, traceOwners } = state;
|
|
155
|
-
let artifactManifest = state.artifactManifest;
|
|
156
|
-
let freshSessionOrdinal = state.freshSessionOrdinal;
|
|
157
|
-
let managedSessionActive = state.managedSessionActive;
|
|
158
|
-
let managedSessionCompatibilityWorkaround = state.managedSessionCompatibilityWorkaround;
|
|
159
|
-
let managedSessionHeadedAutosaveDisabled = state.managedSessionHeadedAutosaveDisabled === true;
|
|
160
|
-
let managedSessionHeadedAutosaveInterval = state.managedSessionHeadedAutosaveInterval;
|
|
161
|
-
let managedSessionCwd = state.managedSessionCwd;
|
|
162
|
-
let managedSessionName = state.managedSessionName;
|
|
163
|
-
let managedSessionNamespace = state.managedSessionNamespace;
|
|
164
|
-
let networkRoutesBySession = state.networkRoutesBySession;
|
|
9
|
+
const ownership = captureBrowserOutputOwnership(input);
|
|
165
10
|
try {
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
observeNativeWebMcp(parsed.envelope?.data);
|
|
172
|
-
let parseError = parsed.parseError;
|
|
173
|
-
const recordingStopRecovery = await recoverRecordingStop({
|
|
174
|
-
modelVisible: input.modelVisible,
|
|
175
|
-
artifactManifest, artifactRunStartedAtMs: input.artifactRunStartedAtMs, commandTokens: prepared.commandTokens, cwd,
|
|
176
|
-
envelope: parsed.envelope, namespace: prepared.executionPlan.namespace, parseError, processResult,
|
|
177
|
-
reservation: prepared.executionPlan.sessionName ? state.activeRecordingReservations?.get(getAgentBrowserSessionIdentityKey(prepared.executionPlan.sessionName, prepared.executionPlan.namespace)) : undefined,
|
|
178
|
-
sessionName: prepared.executionPlan.sessionName, signal, stdin: prepared.runtimeToolStdin,
|
|
179
|
-
});
|
|
180
|
-
let presentationEnvelope = recordingStopRecovery?.envelope ?? parsed.envelope;
|
|
181
|
-
let navigationSummary = undefined;
|
|
182
|
-
let failedTransitionReverification = false;
|
|
183
|
-
const repairedScreenshot = await repairScreenshotArtifact({ cwd, envelope: presentationEnvelope, request: prepared.preparedArgs.screenshotPathRequest });
|
|
184
|
-
presentationEnvelope = repairedScreenshot.envelope;
|
|
185
|
-
const repairedBatchScreenshots = await repairBatchScreenshotArtifacts({ cwd, envelope: presentationEnvelope, requests: prepared.preparedArgs.batchScreenshotPathRequests });
|
|
186
|
-
presentationEnvelope = repairedBatchScreenshots.envelope;
|
|
187
|
-
const screenshotArtifactRequest = repairedScreenshot.request;
|
|
188
|
-
const batchScreenshotArtifactRequests = repairedBatchScreenshots.requests;
|
|
189
|
-
const batchCommandSteps = prepared.executionPlan.commandInfo.command === "batch"
|
|
190
|
-
? getUpstreamEffectiveBatchSteps(prepared.commandTokens, prepared.runtimeToolStdin)
|
|
191
|
-
: [];
|
|
192
|
-
const dispatchedCommands = prepared.executionPlan.commandInfo.command !== "batch"
|
|
193
|
-
? [prepared.commandTokens]
|
|
194
|
-
: Array.isArray(presentationEnvelope?.data)
|
|
195
|
-
? presentationEnvelope.data.flatMap((row, index) => isRecord(row) ? [Array.isArray(row.command) && row.command.every((token) => typeof token === "string") ? row.command : batchCommandSteps[index] ?? []] : [])
|
|
196
|
-
: batchCommandSteps;
|
|
197
|
-
const confirmationSessionName = prepared.executionPlan.sessionName ?? "default";
|
|
198
|
-
let readConfirmation = state.sessionPageState.getReadConfirmation(getAgentBrowserSessionIdentityKey(confirmationSessionName, prepared.executionPlan.namespace));
|
|
199
|
-
let readConfirmationEvent;
|
|
200
|
-
const confirmedEffects = [];
|
|
201
|
-
const confirmationRows = prepared.executionPlan.commandInfo.command === "batch" && Array.isArray(presentationEnvelope?.data)
|
|
202
|
-
? presentationEnvelope.data.flatMap((row, index) => isRecord(row) ? [{ tokens: Array.isArray(row.command) && row.command.every(token => typeof token === "string") ? row.command : batchCommandSteps[index] ?? [], data: row.result, index, response: row, succeeded: row.success === true }] : [])
|
|
203
|
-
: [{ tokens: prepared.commandTokens, data: presentationEnvelope?.data, index: 0, response: presentationEnvelope, succeeded: presentationEnvelope?.success === true }];
|
|
204
|
-
for (const row of confirmationRows) {
|
|
205
|
-
if (readConfirmation?.state === "pending" && readConfirmation.source === "native-guarded-action" && typeof readConfirmation.command === "string"
|
|
206
|
-
&& row.tokens.length === 2 && row.tokens[0] === "confirm" && row.tokens[1] === readConfirmation.id
|
|
207
|
-
&& isRecord(row.data) && row.data.confirmed === true && row.data.action === readConfirmation.action
|
|
208
|
-
&& isRecord(row.data.result) && !detectConfirmationRequired(row.data)) {
|
|
209
|
-
confirmedEffects.push({ command: readConfirmation.command, data: row.data.result.data, index: row.index, succeeded: row.succeeded && row.data.result.success === true });
|
|
210
|
-
}
|
|
211
|
-
const transition = nextReadConfirmation({ commandTokens: row.tokens, current: readConfirmation, data: row.data, namespace: prepared.executionPlan.namespace, sessionName: confirmationSessionName, succeeded: row.succeeded });
|
|
212
|
-
if (transition) {
|
|
213
|
-
readConfirmationEvent = transition;
|
|
214
|
-
readConfirmation = transition;
|
|
215
|
-
}
|
|
216
|
-
if (row.tokens.length === 2 && row.tokens[0] === "confirm" && isRecord(row.data) && row.data.confirmed === true && isRecord(row.data.result) && row.data.result.success === false && row.response) {
|
|
217
|
-
row.response.success = false;
|
|
218
|
-
row.response.error = row.data.result.error;
|
|
219
|
-
if (presentationEnvelope)
|
|
220
|
-
presentationEnvelope.success = false;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
const confirmedData = prepared.commandTokens[0] === "confirm" ? confirmedEffects[0]?.data : undefined;
|
|
224
|
-
const confirmedCommand = prepared.commandTokens[0] === "confirm" ? confirmedEffects[0]?.command : undefined;
|
|
225
|
-
const directClose = isCloseCommand(prepared.executionPlan.commandInfo.command)
|
|
226
|
-
|| isSuccessfulNativeConfirmedClose(prepared.commandTokens, presentationEnvelope?.data);
|
|
227
|
-
if (readConfirmationEvent?.state === "pending")
|
|
228
|
-
state.observedBrowserEffects = { ...state.observedBrowserEffects, readConfirmation: readConfirmationEvent };
|
|
229
|
-
const destinationTransition = dispatchedCommands.some((step) => {
|
|
230
|
-
const [command, subcommand] = extractUpstreamCommandTokens(step);
|
|
231
|
-
return isWindowOrDiffPageTransitionCommand(command, subcommand);
|
|
232
|
-
});
|
|
233
|
-
const nestedBatchClose = prepared.executionPlan.commandInfo.command === "batch"
|
|
234
|
-
? getSuccessfulBatchCloseLifecycle(presentationEnvelope?.data, batchCommandSteps)
|
|
235
|
-
: undefined;
|
|
236
|
-
const nestedBatchClosed = nestedBatchClose?.endsClosed === true;
|
|
237
|
-
const nestedBatchRemainsActive = nestedBatchClose?.endsClosed === false;
|
|
238
|
-
const nestedBatchClosesAll = prepared.executionPlan.commandInfo.command === "batch"
|
|
239
|
-
&& batchHasSuccessfulCloseAll(presentationEnvelope?.data, batchCommandSteps);
|
|
240
|
-
const directCloseAllRequested = isCloseAllCommand(extractUpstreamCommandTokens(prepared.commandTokens));
|
|
241
|
-
const directCloseData = confirmedData ?? presentationEnvelope?.data;
|
|
242
|
-
const rawCloseStatePath = directClose && isRecord(directCloseData) && typeof directCloseData.statePath === "string"
|
|
243
|
-
? directCloseData.statePath
|
|
244
|
-
: nestedBatchClose?.statePath;
|
|
245
|
-
if (presentationEnvelope && prepared.exactSensitiveValues.length > 0)
|
|
246
|
-
presentationEnvelope = redactExactSensitiveValue(presentationEnvelope, prepared.exactSensitiveValues);
|
|
247
|
-
const parseFailureOutput = parseError && processResult.stdoutSpillPath
|
|
248
|
-
? { fullOutputUnavailable: "Malformed upstream output was discarded because it may contain sensitive browser data." }
|
|
249
|
-
: {};
|
|
250
|
-
const browserIndependentRead = isBrowserIndependentConfirmation(prepared.readConfirmation) || isBrowserIndependentRead(prepared.commandTokens, prepared.runtimeToolStdin);
|
|
251
|
-
const nativeCommandMayHaveExecuted = !nativePolicyDefinitelyUnestablished(processResult, parsed.envelope, prepared.commandTokens);
|
|
252
|
-
if (state.confirmationPolicyMayBeEstablished !== true)
|
|
253
|
-
state.confirmationPolicyMayBeEstablished = nativeCommandMayHaveExecuted;
|
|
254
|
-
const processSucceeded = !processResult.timedOut && !processResult.aborted && !processResult.spawnError && processResult.exitCode === 0;
|
|
255
|
-
const plainTextInspection = prepared.executionPlan.plainTextInspection && processSucceeded;
|
|
256
|
-
const parseSucceeded = plainTextInspection || parseError === undefined;
|
|
257
|
-
if (isStreamEnableAlreadyEnabledNoop({ command: prepared.executionPlan.commandInfo.command, envelope: presentationEnvelope, processSucceeded, subcommand: prepared.executionPlan.commandInfo.subcommand })) {
|
|
258
|
-
presentationEnvelope = { success: true, data: { alreadyEnabled: true, enabled: true, message: getEnvelopeErrorString(presentationEnvelope) ?? "Stream already enabled" } };
|
|
259
|
-
}
|
|
260
|
-
const envelopeSuccess = plainTextInspection ? true : presentationEnvelope?.success !== false && !detectConfirmationRequired(presentationEnvelope?.data);
|
|
261
|
-
let succeeded = (processSucceeded && parseSucceeded && envelopeSuccess) || recordingStopRecovery?.recovery.healed === true;
|
|
262
|
-
const inspectionText = plainTextInspection ? processResult.stdout.trim() : undefined;
|
|
263
|
-
const unobservedMutation = processResult.agentBrowserStarted && !plainTextInspection
|
|
264
|
-
&& (processResult.aborted || processResult.timedOut || !parseSucceeded || presentationEnvelope === undefined)
|
|
265
|
-
&& (prepared.executionPlan.commandInfo.command === "batch" ? batchCommandSteps : [prepared.commandTokens]).some(step => {
|
|
266
|
-
const action = step[0] === "find" ? step[step[1] === "nth" ? 4 : 3] ?? "click" : step[0];
|
|
267
|
-
return isPageMutationCommand(action, step[1]);
|
|
268
|
-
});
|
|
269
|
-
const sessionStateKey = getSessionContextKey(prepared.executionPlan.sessionName, prepared.executionPlan.namespace);
|
|
270
|
-
const closeAllApplied = nestedBatchClosesAll || (directCloseAllRequested && succeeded);
|
|
271
|
-
if (sessionStateKey && processResult.agentBrowserStarted && sessionPageState.get(sessionStateKey).tabReopenPending === true) {
|
|
272
|
-
if (dispatchedCommands.some(commandChoosesSessionTabTarget))
|
|
273
|
-
sessionPageState.setTabReopenPending({ pending: false, sessionName: sessionStateKey, update: sessionPageStateUpdate });
|
|
274
|
-
}
|
|
275
|
-
if (closeAllApplied) {
|
|
276
|
-
networkRoutesBySession = withoutNamespaceEntries(networkRoutesBySession, prepared.executionPlan.namespace);
|
|
277
|
-
deleteIdentityKeysInNamespace(state.attachedSessionKeys, prepared.executionPlan.namespace);
|
|
278
|
-
deleteIdentityKeysInNamespace(traceOwners, prepared.executionPlan.namespace);
|
|
279
|
-
sessionPageState.clearNamespace(prepared.executionPlan.namespace);
|
|
280
|
-
const retainedSessionKey = nestedBatchRemainsActive ? sessionStateKey : undefined;
|
|
281
|
-
for (const [key, owner] of state.ownedManagedSessions) {
|
|
282
|
-
if (!isAgentBrowserSessionIdentityKeyInNamespace(key, prepared.executionPlan.namespace) || key === retainedSessionKey)
|
|
283
|
-
continue;
|
|
284
|
-
state.closedManagedSessionNames.add(key);
|
|
285
|
-
state.managedSessionRestoreState.clear(owner.sessionName, owner.namespace);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
else if (nestedBatchClose && sessionStateKey) {
|
|
289
|
-
networkRoutesBySession = new Map(networkRoutesBySession);
|
|
290
|
-
networkRoutesBySession.delete(sessionStateKey);
|
|
291
|
-
sessionPageState.clearSession(sessionStateKey);
|
|
292
|
-
}
|
|
293
|
-
if (sessionStateKey && nestedBatchRemainsActive) {
|
|
294
|
-
const confirmActions = getAgentBrowserProcessEnvironment().AGENT_BROWSER_CONFIRM_ACTIONS;
|
|
295
|
-
if (confirmActions !== undefined)
|
|
296
|
-
sessionPageState.setConfirmActions(sessionStateKey, confirmActions);
|
|
297
|
-
}
|
|
298
|
-
if (prepared.executionPlan.commandInfo.command === "batch" && Array.isArray(presentationEnvelope?.data)) {
|
|
299
|
-
for (const [index, row] of presentationEnvelope.data.entries()) {
|
|
300
|
-
if (!isRecord(row))
|
|
301
|
-
continue;
|
|
302
|
-
const rowCommand = Array.isArray(row.command) && row.command.every((token) => typeof token === "string")
|
|
303
|
-
? row.command
|
|
304
|
-
: batchCommandSteps[index];
|
|
305
|
-
if (!rowCommand)
|
|
306
|
-
continue;
|
|
307
|
-
const [command, subcommand] = extractUpstreamCommandTokens(rowCommand);
|
|
308
|
-
updateTraceOwnerState({ command, sessionName: sessionStateKey, subcommand, succeeded: row.success === true && !detectConfirmationRequired(row.result), traceOwners });
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
else {
|
|
312
|
-
updateTraceOwnerState({ command: directClose ? "close" : prepared.executionPlan.commandInfo.command, sessionName: sessionStateKey, subcommand: prepared.executionPlan.commandInfo.subcommand, succeeded, traceOwners });
|
|
313
|
-
}
|
|
314
|
-
let clickDispatchDiagnostic;
|
|
315
|
-
if (succeeded && prepared.clickDispatchProbe) {
|
|
316
|
-
clickDispatchDiagnostic = await collectClickDispatchDiagnostic({ cwd, namespace: prepared.executionPlan.namespace, probe: prepared.clickDispatchProbe, sessionName: prepared.executionPlan.sessionName, signal });
|
|
317
|
-
if (clickDispatchDiagnostic) {
|
|
318
|
-
succeeded = false;
|
|
319
|
-
presentationEnvelope = { ...(presentationEnvelope ?? {}), error: clickDispatchDiagnostic.summary, success: false };
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
const tabTransition = confirmedEffects.some(effect => effect.command === "tab") || dispatchedCommands.some((step) => {
|
|
323
|
-
const [command, subcommand] = extractUpstreamCommandTokens(step);
|
|
324
|
-
return command === "tab" && subcommand !== undefined && subcommand !== "list";
|
|
325
|
-
});
|
|
326
|
-
// Non-page rows (including a failed prefix) cannot retire a cold target for a navigation that never ran.
|
|
327
|
-
const resultingPageState = !nativeCommandMayHaveExecuted || detectConfirmationRequired(presentationEnvelope?.data) || sessionPageState.get(sessionStateKey).tabReopenPending === true
|
|
328
|
-
? { currentPageUrl: prepared.priorSessionTabTarget?.url, pageTargetMayHaveChanged: false, pageUrlUnknown: prepared.priorSessionTabTargetUnknown === true }
|
|
329
|
-
: getResultingPageTargetState({
|
|
330
|
-
args: prepared.executionPlan.effectiveArgs,
|
|
331
|
-
executedBatchSteps: dispatchedCommands,
|
|
332
|
-
batchResults: presentationEnvelope?.data,
|
|
333
|
-
currentPageUrl: prepared.priorSessionTabTarget?.url,
|
|
334
|
-
pageUrlUnknown: prepared.priorSessionTabTargetUnknown === true,
|
|
335
|
-
});
|
|
336
|
-
if ((succeeded || processSucceeded && confirmedEffects.some(effect => effect.succeeded)) && readConfirmation?.state !== "pending" && !nestedBatchClosed && !directClose &&
|
|
337
|
-
(confirmedEffects.some(effect => shouldCaptureNavigationSummary(effect.command, effect.data)) || shouldCaptureNavigationSummary(prepared.executionPlan.commandInfo.command, presentationEnvelope?.data, prepared.executionPlan.commandInfo.subcommand) ||
|
|
338
|
-
(prepared.executionPlan.commandInfo.command === "batch" && dispatchedCommands.some(([command, subcommand]) => isNavigationObservableCommandName(command, subcommand))) ||
|
|
339
|
-
shouldCaptureSemanticActionNavigationSummary(prepared.compiledSemanticAction, presentationEnvelope?.data) ||
|
|
340
|
-
commandRequiresLivePageVerification(prepared.executionPlan.effectiveArgs, prepared.runtimeToolStdin) ||
|
|
341
|
-
destinationTransition || tabTransition)) {
|
|
342
|
-
navigationSummary = await collectNavigationSummary({ cwd, namespace: prepared.executionPlan.namespace, priorTarget: prepared.priorSessionTabTarget, reusePriorTitle: !tabTransition, sessionName: prepared.executionPlan.sessionName, signal });
|
|
343
|
-
}
|
|
344
|
-
// Failed transitions may already have changed the page; keep only a live observed URL.
|
|
345
|
-
if (succeeded === false && navigationSummary === undefined && readConfirmation?.state !== "pending" &&
|
|
346
|
-
processResult.agentBrowserStarted && nativeCommandMayHaveExecuted &&
|
|
347
|
-
!processResult.aborted &&
|
|
348
|
-
!processResult.timedOut &&
|
|
349
|
-
!nestedBatchClosed && !directClose &&
|
|
350
|
-
(confirmedEffects.some(effect => isUnverifiedPageTransitionCommand(effect.command)) || dispatchedCommands.some((step) => {
|
|
351
|
-
const [command, subcommand] = extractUpstreamCommandTokens(step);
|
|
352
|
-
return (prepared.executionPlan.commandInfo.command === "batch" && isOpenNavigationCommand(command))
|
|
353
|
-
|| isUnverifiedPageTransitionCommand(command, subcommand);
|
|
354
|
-
}))) {
|
|
355
|
-
navigationSummary = await collectNavigationSummary({ cwd, namespace: prepared.executionPlan.namespace, priorTarget: prepared.priorSessionTabTarget, sessionName: prepared.executionPlan.sessionName, signal });
|
|
356
|
-
// Re-verifying a failed transition's URL does not make its prior refs valid.
|
|
357
|
-
failedTransitionReverification = navigationSummary !== undefined;
|
|
358
|
-
}
|
|
359
|
-
if (!textOutput && navigationSummary && presentationEnvelope && prepared.executionPlan.commandInfo.command !== "eval" && !Array.isArray(presentationEnvelope.data))
|
|
360
|
-
presentationEnvelope = { ...presentationEnvelope, data: mergeNavigationSummaryIntoData(presentationEnvelope.data, navigationSummary) };
|
|
361
|
-
let overlayBlockerDiagnostic;
|
|
362
|
-
let openResultTabCorrection;
|
|
363
|
-
if (succeeded && prepared.executionPlan.sessionName && prepared.executionPlan.startupScopedFlags.some((flag) => OPEN_RESULT_TAB_CORRECTION_FLAGS.has(flag)) && isOpenNavigationCommand(prepared.executionPlan.commandInfo.command) && !commandExplicitlyTargetsAboutBlank(prepared.commandTokens)) {
|
|
364
|
-
const targetTitle = extractStringResultField(presentationEnvelope?.data, "title");
|
|
365
|
-
const targetUrl = extractStringResultField(presentationEnvelope?.data, "url");
|
|
366
|
-
const plannedTabCorrection = await collectOpenResultTabCorrection({ cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal, targetTitle, targetUrl });
|
|
367
|
-
if (plannedTabCorrection)
|
|
368
|
-
openResultTabCorrection = await applyOpenResultTabCorrection({ correction: plannedTabCorrection, cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal });
|
|
369
|
-
}
|
|
370
|
-
const verifiesCurrentUrl = prepared.executionPlan.commandInfo.command === "get" && prepared.executionPlan.commandInfo.subcommand === "url"
|
|
371
|
-
|| readConfirmationEvent?.state === "cleared" && prepared.readConfirmation?.source === "native-guarded-action" && extractSessionTabTargetFromCommandData(prepared.commandTokens, presentationEnvelope?.data) !== undefined;
|
|
372
|
-
const trustsReportedPageTarget = !resultingPageState.pageUrlUnknown || verifiesCurrentUrl;
|
|
373
|
-
const pendingWebMcpMutation = isPendingWebMcpMutation(prepared.executionPlan.commandInfo.command, prepared.executionPlan.commandInfo.subcommand, presentationEnvelope?.data) || (prepared.executionPlan.commandInfo.command === "batch" && batchHasPendingWebMcpMutation(presentationEnvelope?.data));
|
|
374
|
-
const failedWebMcpSettlement = prepared.priorSessionTabTargetUnknown === true && ((!succeeded && isWebMcpSettlementCommand(prepared.executionPlan.commandInfo.command, prepared.executionPlan.commandInfo.subcommand))
|
|
375
|
-
|| (prepared.executionPlan.commandInfo.command === "batch" && batchHasFailedWebMcpSettlement(presentationEnvelope?.data)));
|
|
376
|
-
const unsettledWebMcpMutation = pendingWebMcpMutation || failedWebMcpSettlement;
|
|
377
|
-
const helperConfirmation = parseReadConfirmation(state.observedBrowserEffects?.readConfirmation);
|
|
378
|
-
// Main pending installs this object above; only a helper can replace it during post-processing.
|
|
379
|
-
let confirmationFromHelper = state.observedBrowserEffects?.readConfirmation !== readConfirmationEvent;
|
|
380
|
-
if (confirmationFromHelper && helperConfirmation?.state === "pending") {
|
|
381
|
-
readConfirmationEvent = helperConfirmation;
|
|
382
|
-
readConfirmation = helperConfirmation;
|
|
383
|
-
succeeded = false;
|
|
384
|
-
}
|
|
385
|
-
const pageTargetData = textOutput ? undefined : presentationEnvelope?.data;
|
|
386
|
-
let observedSessionTabTarget = unsettledWebMcpMutation || (unobservedMutation && !failedTransitionReverification)
|
|
387
|
-
? undefined
|
|
388
|
-
: normalizeSessionTabTarget(navigationSummary)
|
|
389
|
-
?? (trustsReportedPageTarget ? extractSessionTabTargetFromBatchResults(pageTargetData) : undefined)
|
|
390
|
-
?? (succeeded && trustsReportedPageTarget ? extractSessionTabTargetFromCommandData(prepared.commandTokens, pageTargetData) : undefined);
|
|
391
|
-
if (observedSessionTabTarget && readConfirmation?.state !== "pending" && !browserIndependentRead && !nestedBatchClosed && !directClose) {
|
|
392
|
-
const reportedTarget = prepared.executionPlan.commandInfo.command === "batch"
|
|
393
|
-
? extractSessionTabTargetFromBatchResults(pageTargetData)
|
|
394
|
-
: prepared.commandTokens[0] === "tab" && prepared.commandTokens[1] === "close" ? undefined
|
|
395
|
-
: extractSessionTabTargetFromCommandData(prepared.commandTokens, pageTargetData);
|
|
396
|
-
if (reportedTarget?.targetId)
|
|
397
|
-
observedSessionTabTarget.targetId = reportedTarget.targetId;
|
|
398
|
-
else
|
|
399
|
-
observedSessionTabTarget = await collectSessionTabTarget({ cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal, target: observedSessionTabTarget });
|
|
400
|
-
}
|
|
401
|
-
const safeObservedSessionTabTarget = observedSessionTabTarget;
|
|
402
|
-
let currentSessionTabTarget = safeObservedSessionTabTarget;
|
|
403
|
-
if (!currentSessionTabTarget && nestedBatchClose === undefined && !unobservedMutation) {
|
|
404
|
-
// Window/diff responses do not report the final URL; URL2 is intent, not redirect evidence.
|
|
405
|
-
currentSessionTabTarget = resultingPageState.pageTargetMayHaveChanged
|
|
406
|
-
? succeeded && !destinationTransition ? normalizeSessionTabTarget({ url: resultingPageState.currentPageUrl }) : undefined
|
|
407
|
-
: deriveSessionTabTarget({ command: directClose ? "close" : prepared.executionPlan.commandInfo.command, data: pageTargetData, navigationSummary, previousTarget: prepared.priorSessionTabTarget, subcommand: prepared.executionPlan.commandInfo.subcommand });
|
|
408
|
-
}
|
|
409
|
-
let aboutBlankSessionMismatch;
|
|
410
|
-
let electronPostCommandHealth;
|
|
411
|
-
let electronRefFreshnessDiagnostic;
|
|
412
|
-
let electronSessionMismatch;
|
|
413
|
-
let electronStatusAfterCommand;
|
|
414
|
-
const explicitlyTargetsAboutBlank = dispatchedCommands.some((step) => commandExplicitlyTargetsAboutBlank(extractUpstreamCommandTokens(step)));
|
|
415
|
-
const shouldTreatAboutBlankAsMismatch = succeeded && !tabTransition && !destinationTransition && !explicitlyTargetsAboutBlank && nestedBatchClose === undefined && prepared.priorSessionTabTarget !== undefined && !isAboutBlankSessionTabTarget(prepared.priorSessionTabTarget) && isAboutBlankSessionTabTarget(observedSessionTabTarget ?? currentSessionTabTarget);
|
|
416
|
-
let sessionTabCorrection = prepared.sessionTabCorrection;
|
|
417
|
-
if (shouldTreatAboutBlankAsMismatch && prepared.priorSessionTabTarget) {
|
|
418
|
-
const aboutBlankObservedTarget = observedSessionTabTarget ?? currentSessionTabTarget;
|
|
419
|
-
const aboutBlankRecovery = await collectSessionTabSelection({ cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal, target: prepared.priorSessionTabTarget });
|
|
420
|
-
const appliedAboutBlankRecovery = aboutBlankRecovery ? await applyOpenResultTabCorrection({ correction: aboutBlankRecovery, cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal }) : undefined;
|
|
421
|
-
if (appliedAboutBlankRecovery) {
|
|
422
|
-
sessionTabCorrection = appliedAboutBlankRecovery;
|
|
423
|
-
currentSessionTabTarget = prepared.priorSessionTabTarget;
|
|
424
|
-
}
|
|
425
|
-
else
|
|
426
|
-
currentSessionTabTarget = aboutBlankObservedTarget ?? normalizeSessionTabTarget({ url: "about:blank" });
|
|
427
|
-
aboutBlankSessionMismatch = { activeUrl: "about:blank", recoveryApplied: appliedAboutBlankRecovery !== undefined, recoveryHint: buildAboutBlankRecoveryHint(), targetTitle: prepared.priorSessionTabTarget.title, targetUrl: prepared.priorSessionTabTarget.url };
|
|
428
|
-
const electronRecord = findElectronLaunchRecordForSession(prepared.executionPlan.sessionName, electronLaunchRecords, prepared.executionPlan.namespace);
|
|
429
|
-
if (electronRecord && prepared.executionPlan.sessionName) {
|
|
430
|
-
electronStatusAfterCommand = await inspectElectronLaunchStatus(electronRecord);
|
|
431
|
-
electronSessionMismatch = buildElectronSessionMismatch({ managedSession: { sessionName: prepared.executionPlan.sessionName, title: aboutBlankObservedTarget?.title, url: aboutBlankObservedTarget?.url ?? "about:blank" }, record: electronRecord, statusTargets: electronStatusAfterCommand.targets });
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
if (succeeded && prepared.priorSessionTabTarget && !sessionTabCorrection && !aboutBlankSessionMismatch && !commandExplicitlyTargetsAboutBlank(prepared.commandTokens) && observedSessionTabTarget && shouldCorrectSessionTabAfterCommand({ command: prepared.executionPlan.commandInfo.command, pinningRequired: prepared.sessionTabPinningReason !== undefined, sessionName: prepared.executionPlan.sessionName })) {
|
|
435
|
-
const postCommandTabCorrection = await collectSessionTabSelection({ cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal, target: observedSessionTabTarget });
|
|
436
|
-
if (postCommandTabCorrection) {
|
|
437
|
-
const appliedPostCommandCorrection = await applyOpenResultTabCorrection({ correction: postCommandTabCorrection, cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal });
|
|
438
|
-
if (appliedPostCommandCorrection && !sessionTabCorrection)
|
|
439
|
-
sessionTabCorrection = appliedPostCommandCorrection;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
const electronRecordForCommand = findElectronLaunchRecordForSession(prepared.executionPlan.sessionName, electronLaunchRecords, prepared.executionPlan.namespace);
|
|
443
|
-
if (succeeded && electronRecordForCommand && shouldInspectElectronPostCommandHealth(prepared.executionPlan.commandInfo.command)) {
|
|
444
|
-
electronStatusAfterCommand ??= await inspectElectronLaunchStatus(electronRecordForCommand);
|
|
445
|
-
electronPostCommandHealth = buildElectronPostCommandHealthDiagnostic({ command: prepared.executionPlan.commandInfo.command, record: electronRecordForCommand, status: electronStatusAfterCommand, target: observedSessionTabTarget ?? currentSessionTabTarget });
|
|
446
|
-
if (electronPostCommandHealth && electronPostCommandHealth.reason !== "process-dead") {
|
|
447
|
-
await sleepMs(electronPostCommandStatusSettleMs);
|
|
448
|
-
electronStatusAfterCommand = await inspectElectronLaunchStatus(electronRecordForCommand);
|
|
449
|
-
electronPostCommandHealth = buildElectronPostCommandHealthDiagnostic({ command: prepared.executionPlan.commandInfo.command, record: electronRecordForCommand, status: electronStatusAfterCommand, target: observedSessionTabTarget ?? currentSessionTabTarget });
|
|
450
|
-
}
|
|
451
|
-
if (electronPostCommandHealth)
|
|
452
|
-
succeeded = false;
|
|
453
|
-
}
|
|
454
|
-
let fillVerificationDiagnostic;
|
|
455
|
-
let selectorTextVisibilityDiagnostics = [];
|
|
456
|
-
let electronBroadGetTextScopeDiagnostics = [];
|
|
457
|
-
const timeoutPartialProgress = processResult.timedOut && !recordingStopRecovery && !prepared.readConfirmation ? await collectTimeoutPartialProgress({ commandTokens: prepared.commandTokens, compiledJob: prepared.compiledJob, cwd, operationCwd: input.operationCwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, stdin: prepared.runtimeToolStdin }) : undefined;
|
|
458
|
-
if (!currentSessionTabTarget && timeoutPartialProgress?.liveUrlRecovered === true) {
|
|
459
|
-
currentSessionTabTarget = normalizeSessionTabTarget(timeoutPartialProgress.currentPage);
|
|
460
|
-
}
|
|
461
|
-
if (succeeded) {
|
|
462
|
-
const fillRefSnapshot = prepared.resolvedSemanticActionRefSnapshot ?? prepared.priorRefSnapshotState;
|
|
463
|
-
fillVerificationDiagnostic = await collectFillVerificationDiagnostic({ commandTokens: prepared.commandTokens, cwd, forceValueVerification: electronRecordForCommand !== undefined, namespace: prepared.executionPlan.namespace, refSnapshot: fillRefSnapshot, sessionName: prepared.executionPlan.sessionName, signal });
|
|
464
|
-
}
|
|
465
|
-
if (succeeded && electronRecordForCommand) {
|
|
466
|
-
electronRefFreshnessDiagnostic = buildElectronRefFreshnessDiagnostic({ command: prepared.executionPlan.commandInfo.command, commandTokens: prepared.commandTokens, record: electronRecordForCommand, sessionName: prepared.executionPlan.sessionName, stdin: prepared.runtimeToolStdin });
|
|
467
|
-
}
|
|
468
|
-
if (succeeded && prepared.executionPlan.commandInfo.command === "snapshot") {
|
|
469
|
-
overlayBlockerDiagnostic = collectSnapshotOverlayBlockerDiagnostic(presentationEnvelope?.data);
|
|
470
|
-
}
|
|
471
|
-
if (succeeded && !overlayBlockerDiagnostic && !sessionTabCorrection && !aboutBlankSessionMismatch && !electronRecordForCommand && !clickDispatchDiagnostic)
|
|
472
|
-
overlayBlockerDiagnostic = await collectOverlayBlockerDiagnostic({ command: prepared.executionPlan.commandInfo.command, cwd, data: presentationEnvelope?.data, namespace: prepared.executionPlan.namespace, navigationSummary, priorTarget: prepared.priorSessionTabTarget, sessionName: prepared.executionPlan.sessionName, signal });
|
|
473
|
-
if (succeeded) {
|
|
474
|
-
selectorTextVisibilityDiagnostics = await collectSelectorTextVisibilityDiagnostics({ commandInfo: prepared.executionPlan.commandInfo, commandTokens: prepared.commandTokens, cwd, data: presentationEnvelope?.data, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal });
|
|
475
|
-
if (electronRecordForCommand)
|
|
476
|
-
electronBroadGetTextScopeDiagnostics = collectElectronBroadGetTextScopeDiagnostics({ commandInfo: prepared.executionPlan.commandInfo, commandTokens: prepared.commandTokens, currentTarget: currentSessionTabTarget, data: presentationEnvelope?.data, electronLaunchRecords, namespace: prepared.executionPlan.namespace, priorTarget: prepared.priorSessionTabTarget, sessionName: prepared.executionPlan.sessionName });
|
|
477
|
-
}
|
|
478
|
-
const activeNetworkRoutes = sessionStateKey ? networkRoutesBySession.get(sessionStateKey) : undefined;
|
|
479
|
-
const networkRouteDiagnostics = succeeded && prepared.executionPlan.commandInfo.command === "network" && prepared.executionPlan.commandInfo.subcommand === "requests" && prepared.executionPlan.sessionName
|
|
480
|
-
? buildNetworkRouteDiagnostics(presentationEnvelope?.data, activeNetworkRoutes)
|
|
481
|
-
: undefined;
|
|
482
|
-
networkRoutesBySession = applyNetworkRouteState({ commandTokens: prepared.commandTokens, routesBySession: networkRoutesBySession, sessionName: sessionStateKey, succeeded });
|
|
483
|
-
const comboboxFocusDiagnostic = succeeded ? await collectComboboxFocusDiagnostic({ command: prepared.executionPlan.commandInfo.command, commandTokens: prepared.commandTokens, cwd, namespace: prepared.executionPlan.namespace, semanticAction: prepared.compiledSemanticAction, sessionName: prepared.executionPlan.sessionName, signal }) : undefined;
|
|
484
|
-
const recordingDependencyWarning = await collectRecordingDependencyWarning({ command: prepared.executionPlan.commandInfo.command, commandTokens: prepared.commandTokens, succeeded });
|
|
485
|
-
const scrollNoopDiagnostic = succeeded && prepared.shouldProbeScrollNoop ? buildScrollNoopDiagnostic(prepared.scrollPositionBefore, await collectScrollPositionSnapshot({ cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal })) : undefined;
|
|
486
|
-
const batchRefSnapshotState = prepared.executionPlan.commandInfo.command === "batch" ? extractLatestRefSnapshotStateFromBatchResults(Array.isArray(presentationEnvelope?.data) ? presentationEnvelope.data.map((row, index) => {
|
|
487
|
-
const snapshot = confirmedEffects.find(effect => effect.index === index && effect.command === "snapshot");
|
|
488
|
-
return snapshot && isRecord(row) ? { ...row, command: ["snapshot"], result: snapshot.data, success: snapshot.succeeded } : row;
|
|
489
|
-
}) : presentationEnvelope?.data) : undefined;
|
|
490
|
-
let currentRefSnapshot;
|
|
491
|
-
let currentRefSnapshotInvalidation;
|
|
492
|
-
if (sessionStateKey && !browserIndependentRead) {
|
|
493
|
-
const sessionClosed = (directClose && succeeded) || nestedBatchClosed;
|
|
494
|
-
if (sessionClosed) {
|
|
495
|
-
state.attachedSessionKeys.delete(sessionStateKey);
|
|
496
|
-
networkRoutesBySession = new Map(networkRoutesBySession);
|
|
497
|
-
networkRoutesBySession.delete(sessionStateKey);
|
|
498
|
-
sessionPageState.clearSession(sessionStateKey);
|
|
499
|
-
state.closedManagedSessionNames.add(sessionStateKey);
|
|
500
|
-
}
|
|
501
|
-
else {
|
|
502
|
-
// A batch that times out or returns unparseable output yields no result rows, but the daemon
|
|
503
|
-
// may already have executed a recording swap or page-provided WebMCP tool; fall back to the
|
|
504
|
-
// planned steps then. This can over-invalidate by one snapshot, but never under-invalidates.
|
|
505
|
-
const directTransitionInvalidation = getCommandRefSnapshotInvalidation(prepared.commandTokens);
|
|
506
|
-
const plannedBatchTransitionInvalidation = !Array.isArray(presentationEnvelope?.data)
|
|
507
|
-
? batchCommandSteps.map(getCommandRefSnapshotInvalidation).find((invalidation) => invalidation !== undefined)
|
|
508
|
-
: undefined;
|
|
509
|
-
const pageTransitionInvalidation = unobservedMutation && !failedTransitionReverification
|
|
510
|
-
? buildPageTransitionRefSnapshotInvalidation("A dispatched mutation was interrupted without a final outcome. Verify the current URL and take a fresh snapshot before deciding whether to retry.")
|
|
511
|
-
: unsettledWebMcpMutation
|
|
512
|
-
? buildPageTransitionRefSnapshotInvalidation("A detached WebMCP invocation is still pending or failed to settle and can mutate, rerender, or navigate the page, so prior snapshot refs remain invalid after URL verification. Run webmcp result or cancel, then take a fresh snapshot before using page-scoped refs.")
|
|
513
|
-
: processResult.agentBrowserStarted && nativeCommandMayHaveExecuted && (directTransitionInvalidation || plannedBatchTransitionInvalidation)
|
|
514
|
-
? directTransitionInvalidation ?? plannedBatchTransitionInvalidation
|
|
515
|
-
: failedTransitionReverification
|
|
516
|
-
? buildPageTransitionRefSnapshotInvalidation("A failed page transition may still have changed the page, so the prior snapshot refs were invalidated. Run snapshot -i before using page-scoped refs.")
|
|
517
|
-
: batchRefSnapshotState?.invalidation?.reason === "page-transition"
|
|
518
|
-
? batchRefSnapshotState.invalidation
|
|
519
|
-
: undefined;
|
|
520
|
-
if (currentSessionTabTarget) {
|
|
521
|
-
const tabUpdate = sessionPageState.applyTabTarget({ sessionName: sessionStateKey, target: currentSessionTabTarget, update: sessionPageStateUpdate });
|
|
522
|
-
if (!tabUpdate.applied && succeeded)
|
|
523
|
-
sessionPageState.markPinning(sessionStateKey, "drift");
|
|
524
|
-
}
|
|
525
|
-
else if (processResult.agentBrowserStarted && (unobservedMutation || resultingPageState.pageUrlUnknown || resultingPageState.pageTargetMayHaveChanged) && !(prepared.commandTokens[0] === "session" && prepared.commandTokens[1] === "info")) {
|
|
526
|
-
sessionPageState.markTabTargetUnknown({ sessionName: sessionStateKey, update: sessionPageStateUpdate });
|
|
527
|
-
}
|
|
528
|
-
let refSnapshot = unsettledWebMcpMutation || unobservedMutation
|
|
529
|
-
? undefined
|
|
530
|
-
: prepared.executionPlan.commandInfo.command === "batch"
|
|
531
|
-
? batchRefSnapshotState?.snapshot
|
|
532
|
-
: succeeded
|
|
533
|
-
? prepared.executionPlan.commandInfo.command === "snapshot" || confirmedCommand === "snapshot" ? extractRefSnapshotFromData(confirmedData ?? presentationEnvelope?.data) : prepared.resolvedSemanticActionRefSnapshot ?? overlayBlockerDiagnostic?.snapshot
|
|
534
|
-
: undefined;
|
|
535
|
-
const refreshArgs = batchRefSnapshotState?.refreshArgs ?? (succeeded && prepared.commandTokens[0] === "snapshot" && isRecord(presentationEnvelope?.data) && isRecord(presentationEnvelope.data.snapshot) && !refSnapshot
|
|
536
|
-
? prepared.commandTokens.filter((token) => token !== "--delta" && token !== "--full") : undefined);
|
|
537
|
-
// Native owns delta baselines. Read complete refs without advancing that baseline
|
|
538
|
-
// rather than maintaining a second revision/tree cache in the wrapper.
|
|
539
|
-
if (refreshArgs && readConfirmation?.state !== "pending" && !unsettledWebMcpMutation && !unobservedMutation) {
|
|
540
|
-
refSnapshot = extractRefSnapshotFromData(await runSessionCommandData({ args: refreshArgs, cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal }));
|
|
541
|
-
if (!refSnapshot)
|
|
542
|
-
sessionPageState.applyRefSnapshotInvalidation({ invalidation: buildPageTransitionRefSnapshotInvalidation("The native snapshot delta did not include complete refs and the full ref read failed. Run snapshot -i before using refs."), sessionName: sessionStateKey, update: sessionPageStateUpdate });
|
|
543
|
-
}
|
|
544
|
-
if (refSnapshot) {
|
|
545
|
-
const refUpdate = sessionPageState.applyRefSnapshot({ fallbackTarget: currentSessionTabTarget, sessionName: sessionStateKey, snapshot: refSnapshot, update: sessionPageStateUpdate });
|
|
546
|
-
currentRefSnapshot = refUpdate.refSnapshot;
|
|
547
|
-
currentRefSnapshotInvalidation = refUpdate.refSnapshotInvalidation;
|
|
548
|
-
}
|
|
549
|
-
else if (pageTransitionInvalidation) {
|
|
550
|
-
const refUpdate = sessionPageState.applyRefSnapshotInvalidation({ invalidation: pageTransitionInvalidation, sessionName: sessionStateKey, update: sessionPageStateUpdate });
|
|
551
|
-
currentRefSnapshot = refUpdate.refSnapshot;
|
|
552
|
-
currentRefSnapshotInvalidation = refUpdate.refSnapshotInvalidation;
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
const stateView = sessionPageState.get(sessionStateKey);
|
|
556
|
-
currentRefSnapshot = stateView.refSnapshot;
|
|
557
|
-
currentRefSnapshotInvalidation = stateView.refSnapshotInvalidation;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
const priorManagedSessionActive = managedSessionActive;
|
|
562
|
-
const priorManagedSessionCwd = managedSessionCwd;
|
|
563
|
-
const priorManagedSessionHeadedAutosaveInterval = managedSessionHeadedAutosaveInterval;
|
|
564
|
-
const priorManagedSessionName = managedSessionName;
|
|
565
|
-
const priorManagedSessionNamespace = managedSessionNamespace;
|
|
566
|
-
const priorManagedSessionKey = getSessionContextKey(priorManagedSessionName, priorManagedSessionNamespace) ?? priorManagedSessionName;
|
|
567
|
-
const closeAllTargetsPriorManagedSession = closeAllApplied
|
|
568
|
-
&& priorManagedSessionActive
|
|
569
|
-
&& isAgentBrowserSessionIdentityKeyInNamespace(priorManagedSessionKey, prepared.executionPlan.namespace);
|
|
570
|
-
const closeAllRetainsPriorManagedSession = closeAllTargetsPriorManagedSession
|
|
571
|
-
&& nestedBatchRemainsActive
|
|
572
|
-
&& sessionStateKey === priorManagedSessionKey;
|
|
573
|
-
const closeAllClosesPriorManagedSession = closeAllTargetsPriorManagedSession && !closeAllRetainsPriorManagedSession;
|
|
574
|
-
const commandClosesSession = directClose || nestedBatchClosed || closeAllClosesPriorManagedSession;
|
|
575
|
-
const closeCommandSucceeded = (directClose && succeeded) || nestedBatchClosed || closeAllClosesPriorManagedSession;
|
|
576
|
-
const closeTargetsPriorManagedNamespace = prepared.executionPlan.namespace === priorManagedSessionNamespace;
|
|
577
|
-
const managedCloseSessionName = closeAllClosesPriorManagedSession
|
|
578
|
-
? priorManagedSessionName
|
|
579
|
-
: closeCommandSucceeded && prepared.executionPlan.sessionName === priorManagedSessionName && closeTargetsPriorManagedNamespace
|
|
580
|
-
? prepared.executionPlan.sessionName
|
|
581
|
-
: prepared.executionPlan.managedSessionName;
|
|
582
|
-
const postLaunchBatchFailure = !succeeded && processSucceeded && parseSucceeded && prepared.sessionMode === "fresh" && prepared.executionPlan.commandInfo.command === "batch" && batchStartedManagedBrowser(presentationEnvelope?.data);
|
|
583
|
-
const postLaunchTimeoutWithPage = !succeeded && processResult.timedOut && prepared.sessionMode === "fresh" && prepared.executionPlan.commandInfo.command === "batch" && timeoutPartialProgress?.liveUrlRecovered === true;
|
|
584
|
-
const failedFreshSessionMayHaveStarted = !succeeded
|
|
585
|
-
&& (processResult.agentBrowserStarted || (!processResult.aborted && processResult.spawnError === undefined))
|
|
586
|
-
&& prepared.sessionMode === "fresh"
|
|
587
|
-
&& prepared.executionPlan.managedSessionName === prepared.executionPlan.sessionName;
|
|
588
|
-
const failedFreshDaemon = failedFreshSessionMayHaveStarted && prepared.executionPlan.sessionName
|
|
589
|
-
? await inspectManagedSessionDaemon({
|
|
590
|
-
cwd,
|
|
591
|
-
headedManagedAutosaveInterval: prepared.ownedManagedSessionContext?.headedManagedAutosaveInterval,
|
|
592
|
-
namespace: prepared.executionPlan.namespace,
|
|
593
|
-
sessionName: prepared.executionPlan.sessionName,
|
|
594
|
-
timeoutMs: Math.min(implicitSessionCloseTimeoutMs, 2_000),
|
|
595
|
-
})
|
|
596
|
-
: undefined;
|
|
597
|
-
if (failedFreshDaemon?.status === "active") {
|
|
598
|
-
state.managedSessionRestoreState.recordDaemonRestoreKey(prepared.executionPlan.sessionName, prepared.executionPlan.namespace, failedFreshDaemon.restoreKey);
|
|
599
|
-
}
|
|
600
|
-
// Only a confirmed inactive daemon proves that a started fresh command did not establish browser ownership.
|
|
601
|
-
const postLaunchFreshFailure = failedFreshDaemon !== undefined && failedFreshDaemon.status !== "inactive";
|
|
602
|
-
const managedTransitionSucceeded = succeeded || nestedBatchClosed || nestedBatchRemainsActive || postLaunchBatchFailure || postLaunchTimeoutWithPage || postLaunchFreshFailure;
|
|
603
|
-
const managedSessionState = resolveManagedSessionState({ command: commandClosesSession ? "close" : prepared.executionPlan.commandInfo.command, managedSessionName: managedCloseSessionName, managedSessionNamespace: prepared.executionPlan.namespace, priorActive: priorManagedSessionActive, priorNamespace: priorManagedSessionNamespace, priorSessionName: priorManagedSessionName, succeeded: managedTransitionSucceeded });
|
|
604
|
-
if (!managedTransitionSucceeded && prepared.sessionMode === "fresh" && prepared.executionPlan.managedSessionName) {
|
|
605
|
-
state.managedSessionRestoreState.clear(prepared.executionPlan.managedSessionName, prepared.executionPlan.namespace);
|
|
606
|
-
}
|
|
607
|
-
const replacedManagedSessionName = managedSessionState.replacedSessionName;
|
|
608
|
-
managedSessionActive = managedSessionState.active;
|
|
609
|
-
managedSessionName = managedSessionState.sessionName;
|
|
610
|
-
managedSessionNamespace = managedSessionState.namespace;
|
|
611
|
-
const executionTargetsManagedSession = prepared.executionPlan.sessionName
|
|
612
|
-
&& getAgentBrowserSessionIdentityKey(prepared.executionPlan.sessionName, prepared.executionPlan.namespace)
|
|
613
|
-
=== getAgentBrowserSessionIdentityKey(managedSessionName, managedSessionNamespace);
|
|
614
|
-
if (!managedSessionActive) {
|
|
615
|
-
managedSessionCompatibilityWorkaround = undefined;
|
|
616
|
-
managedSessionHeadedAutosaveDisabled = false;
|
|
617
|
-
managedSessionHeadedAutosaveInterval = undefined;
|
|
618
|
-
}
|
|
619
|
-
else if (managedTransitionSucceeded && executionTargetsManagedSession && prepared.ownedManagedSessionContext && !prepared.ownedManagedSessionContext.reuseOnly) {
|
|
620
|
-
managedSessionCompatibilityWorkaround = prepared.compatibilityWorkaround;
|
|
621
|
-
managedSessionHeadedAutosaveDisabled = prepared.ownedManagedSessionContext?.headedManagedAutosaveDisabled === true;
|
|
622
|
-
managedSessionHeadedAutosaveInterval = prepared.ownedManagedSessionContext?.headedManagedAutosaveInterval;
|
|
623
|
-
}
|
|
624
|
-
if (closeCommandSucceeded && managedCloseSessionName === priorManagedSessionName && !managedSessionActive) {
|
|
625
|
-
const daemonRestoreKey = state.managedSessionRestoreState.getDaemonRestoreKey(managedCloseSessionName, priorManagedSessionNamespace);
|
|
626
|
-
const ownedRestoreKey = !state.managedSessionRestoreState.isDisabled(managedCloseSessionName, priorManagedSessionNamespace)
|
|
627
|
-
&& isManagedSessionRestoreKey(daemonRestoreKey) ? daemonRestoreKey : null;
|
|
628
|
-
state.managedSessionRestoreState.clear(managedCloseSessionName, priorManagedSessionNamespace);
|
|
629
|
-
pruneOwnedManagedSessionRestoreSnapshots({
|
|
630
|
-
cwd,
|
|
631
|
-
namespace: priorManagedSessionNamespace,
|
|
632
|
-
restoreKey: ownedRestoreKey,
|
|
633
|
-
statePath: rawCloseStatePath,
|
|
634
|
-
});
|
|
635
|
-
freshSessionOrdinal += 1;
|
|
636
|
-
managedSessionName = createFreshSessionName(state.managedSessionBaseName, state.ephemeralSessionSeed, freshSessionOrdinal);
|
|
637
|
-
managedSessionNamespace = undefined;
|
|
638
|
-
}
|
|
639
|
-
let managedSessionOutcome = buildManagedSessionOutcome({ activeAfter: managedSessionActive, activeBefore: priorManagedSessionActive, attemptedSessionName: managedCloseSessionName, command: commandClosesSession ? "close" : prepared.executionPlan.commandInfo.command, currentSessionName: managedSessionName, currentSessionNamespace: managedSessionNamespace, previousSessionName: priorManagedSessionName, replacedSessionName: replacedManagedSessionName, replacedSessionNamespace: priorManagedSessionNamespace, sessionMode: prepared.sessionMode, succeeded: managedTransitionSucceeded });
|
|
640
|
-
if (prepared.executionPlan.managedSessionName && managedTransitionSucceeded && managedSessionActive) {
|
|
641
|
-
if (!priorManagedSessionActive || replacedManagedSessionName)
|
|
642
|
-
managedSessionCwd = cwd;
|
|
643
|
-
managedSessionNamespace = prepared.executionPlan.namespace;
|
|
644
|
-
}
|
|
645
|
-
if (sessionStateKey && succeeded) {
|
|
646
|
-
if (openResultTabCorrection || sessionTabCorrection || aboutBlankSessionMismatch?.recoveryApplied)
|
|
647
|
-
sessionPageState.markPinning(sessionStateKey, "drift");
|
|
648
|
-
else if (prepared.sessionTabPinningReason === "restore" && observedSessionTabTarget)
|
|
649
|
-
sessionPageState.clearRestorePinning(sessionStateKey);
|
|
650
|
-
}
|
|
651
|
-
if (replacedManagedSessionName) {
|
|
652
|
-
const replacedSessionStateKey = getSessionContextKey(replacedManagedSessionName, priorManagedSessionNamespace);
|
|
653
|
-
const replacedSessionKey = replacedSessionStateKey ?? replacedManagedSessionName;
|
|
654
|
-
const replacedCloseError = await closeManagedSession({ confirmActions: sessionPageState.get(replacedSessionKey).confirmActions ?? process.env.AGENT_BROWSER_CONFIRM_ACTIONS, cwd: priorManagedSessionCwd, headedManagedAutosaveInterval: priorManagedSessionHeadedAutosaveInterval, namespace: priorManagedSessionNamespace, preserveAttachedBrowserSession: state.attachedSessionKeys.has(replacedSessionKey), restoreState: state.managedSessionRestoreState, sessionName: replacedManagedSessionName, socketDir: state.ownedManagedSessions.get(replacedSessionKey)?.socketDir, timeoutMs: implicitSessionCloseTimeoutMs });
|
|
655
|
-
if (managedSessionOutcome) {
|
|
656
|
-
managedSessionOutcome = {
|
|
657
|
-
...managedSessionOutcome,
|
|
658
|
-
replacedSessionClosed: !replacedCloseError,
|
|
659
|
-
summary: replacedCloseError
|
|
660
|
-
? `${managedSessionOutcome.summary} Previous session ${replacedManagedSessionName} remains wrapper-owned because automatic close failed; retry an explicit close.`
|
|
661
|
-
: managedSessionOutcome.summary,
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
|
-
if (!replacedCloseError) {
|
|
665
|
-
networkRoutesBySession = new Map(networkRoutesBySession);
|
|
666
|
-
networkRoutesBySession.delete(replacedSessionKey);
|
|
667
|
-
sessionPageState.clearSession(replacedSessionKey);
|
|
668
|
-
state.attachedSessionKeys.delete(replacedSessionKey);
|
|
669
|
-
state.closedManagedSessionNames.add(replacedSessionKey);
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
let electronLaunchRecord;
|
|
673
|
-
let electronFailedConnectCleanup = prepared.electronFailedConnectCleanup;
|
|
674
|
-
let electronHandoff = prepared.electronHandoff;
|
|
675
|
-
if (prepared.electronLaunch) {
|
|
676
|
-
if (succeeded && prepared.executionPlan.sessionName) {
|
|
677
|
-
const electronSessionName = prepared.executionPlan.sessionName;
|
|
678
|
-
const electronSessionStateKey = sessionStateKey ?? electronSessionName;
|
|
679
|
-
electronLaunchRecord = { ...prepared.electronLaunch.record, namespace: prepared.executionPlan.namespace, sessionName: electronSessionName };
|
|
680
|
-
const electronHandoffMode = prepared.compiledElectron?.action === "launch" ? prepared.compiledElectron.handoff : "connect";
|
|
681
|
-
try {
|
|
682
|
-
electronHandoff = await collectElectronHandoff({ cwd, handoff: electronHandoffMode, namespace: prepared.executionPlan.namespace, sessionName: electronSessionName, signal });
|
|
683
|
-
}
|
|
684
|
-
catch (error) {
|
|
685
|
-
electronHandoff = {
|
|
686
|
-
error: error instanceof Error ? error.message : String(error),
|
|
687
|
-
failureCategory: signal?.aborted ? "aborted" : "upstream-error",
|
|
688
|
-
handoff: electronHandoffMode,
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
if (electronHandoff.error) {
|
|
692
|
-
succeeded = false;
|
|
693
|
-
presentationEnvelope = { error: electronHandoff.error, success: false };
|
|
694
|
-
const closeError = await closeManagedSession({ confirmActions: sessionPageState.get(electronSessionStateKey).confirmActions ?? process.env.AGENT_BROWSER_CONFIRM_ACTIONS, cwd, headedManagedAutosaveInterval: prepared.ownedManagedSessionContext?.headedManagedAutosaveInterval, namespace: prepared.executionPlan.namespace, policyLock: prepared.managedSessionPolicyLock, preserveAttachedBrowserSession: input.preserveAttachedBrowserSession, restoreState: state.managedSessionRestoreState, sessionName: electronSessionName, timeoutMs: implicitSessionCloseTimeoutMs });
|
|
695
|
-
electronFailedConnectCleanup = await cleanupElectronLaunchResources({ child: prepared.electronLaunch.child, record: electronLaunchRecord, timeoutMs: implicitSessionCloseTimeoutMs });
|
|
696
|
-
electronLaunchRecord = electronFailedConnectCleanup.record;
|
|
697
|
-
if (electronFailedConnectCleanup.partial) {
|
|
698
|
-
electronLaunchRecords.set(electronLaunchRecord.launchId, electronLaunchRecord);
|
|
699
|
-
electronChildProcesses.set(electronLaunchRecord.launchId, prepared.electronLaunch.child);
|
|
700
|
-
}
|
|
701
|
-
else {
|
|
702
|
-
electronLaunchRecords.delete(electronLaunchRecord.launchId);
|
|
703
|
-
electronChildProcesses.delete(electronLaunchRecord.launchId);
|
|
704
|
-
}
|
|
705
|
-
if (!closeError) {
|
|
706
|
-
state.closedManagedSessionNames.add(electronSessionStateKey);
|
|
707
|
-
networkRoutesBySession = new Map(networkRoutesBySession);
|
|
708
|
-
networkRoutesBySession.delete(electronSessionStateKey);
|
|
709
|
-
sessionPageState.clearSession(electronSessionStateKey);
|
|
710
|
-
if (managedSessionName === electronSessionName && managedSessionNamespace === prepared.executionPlan.namespace) {
|
|
711
|
-
managedSessionActive = false;
|
|
712
|
-
freshSessionOrdinal += 1;
|
|
713
|
-
managedSessionName = createFreshSessionName(state.managedSessionBaseName, state.ephemeralSessionSeed, freshSessionOrdinal);
|
|
714
|
-
managedSessionNamespace = undefined;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
managedSessionOutcome = buildManagedSessionOutcome({ activeAfter: managedSessionActive, activeBefore: priorManagedSessionActive, attemptedSessionName: electronSessionName, command: prepared.executionPlan.commandInfo.command, currentSessionName: managedSessionName, currentSessionNamespace: managedSessionNamespace, previousSessionName: priorManagedSessionName, replacedSessionName: replacedManagedSessionName, replacedSessionNamespace: priorManagedSessionNamespace, sessionMode: prepared.sessionMode, succeeded: false });
|
|
718
|
-
}
|
|
719
|
-
else {
|
|
720
|
-
electronLaunchRecords.set(electronLaunchRecord.launchId, electronLaunchRecord);
|
|
721
|
-
electronChildProcesses.set(electronLaunchRecord.launchId, prepared.electronLaunch.child);
|
|
722
|
-
if (electronHandoff.refSnapshot) {
|
|
723
|
-
const refUpdate = sessionPageState.applyRefSnapshot({ sessionName: electronSessionStateKey, snapshot: electronHandoff.refSnapshot, update: sessionPageStateUpdate });
|
|
724
|
-
currentRefSnapshot = refUpdate.refSnapshot;
|
|
725
|
-
currentRefSnapshotInvalidation = refUpdate.refSnapshotInvalidation;
|
|
726
|
-
if (electronHandoff.refSnapshot.target) {
|
|
727
|
-
const targetUpdate = sessionPageState.applyTabTarget({ sessionName: electronSessionStateKey, target: electronHandoff.refSnapshot.target, update: sessionPageStateUpdate });
|
|
728
|
-
currentSessionTabTarget = targetUpdate.tabTarget;
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
734
|
-
electronFailedConnectCleanup = await cleanupElectronLaunchResources({ child: prepared.electronLaunch.child, record: prepared.electronLaunch.record, timeoutMs: implicitSessionCloseTimeoutMs });
|
|
735
|
-
electronLaunchRecord = electronFailedConnectCleanup.record;
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
let errorText = recordingStopRecovery?.recovery.healed ? undefined : getAgentBrowserErrorText({ aborted: processResult.aborted, command: prepared.executionPlan.commandInfo.command, effectiveArgs: prepared.redactedProcessArgs, envelope: presentationEnvelope, exitCode: processResult.exitCode, parseError, plainTextInspection, staleRefArgs: getStaleRefArgs(prepared.commandTokens, prepared.runtimeToolStdin), spawnError: processResult.spawnError, stderr: processResult.stderr, timedOut: processResult.timedOut, timeoutMs: processResult.timeoutMs, wrapperRecoveryHint: buildWrapperRecoveryHint({ sessionTabCorrection }) });
|
|
739
|
-
if (errorText && presentationEnvelope?.success === false && extractEnvelopeErrorText(presentationEnvelope.error) === undefined)
|
|
740
|
-
presentationEnvelope = { ...presentationEnvelope, error: errorText };
|
|
741
|
-
if (errorText) {
|
|
742
|
-
const clipboardWritePayloadCandidates = getClipboardWritePayloadCandidates(prepared.commandTokens);
|
|
743
|
-
errorText = redactClipboardPermissionEcho(prepared.executionPlan.commandInfo, errorText);
|
|
744
|
-
if (presentationEnvelope?.error !== undefined)
|
|
745
|
-
presentationEnvelope = { ...presentationEnvelope, error: redactClipboardPermissionErrorValue(prepared.executionPlan.commandInfo, presentationEnvelope.error, clipboardWritePayloadCandidates) };
|
|
746
|
-
}
|
|
747
|
-
if ((plainTextUpgrade || textOutput) && errorText)
|
|
748
|
-
presentationEnvelope = { ...presentationEnvelope, success: false, error: errorText };
|
|
749
|
-
const resultRetainsPreparedManagedSession = !managedSessionOutcome || (managedSessionOutcome.activeAfter
|
|
750
|
-
&& managedSessionOutcome.attemptedSessionName === managedSessionOutcome.currentSessionName);
|
|
751
|
-
const resultHeadedManagedAutosaveDisabled = prepared.ownedManagedSessionContext?.headedManagedAutosaveDisabled === true
|
|
752
|
-
&& resultRetainsPreparedManagedSession
|
|
753
|
-
&& !(commandClosesSession && succeeded);
|
|
754
|
-
const resultHeadedManagedAutosaveInterval = resultRetainsPreparedManagedSession && !(commandClosesSession && succeeded)
|
|
755
|
-
? prepared.ownedManagedSessionContext?.headedManagedAutosaveInterval
|
|
756
|
-
: undefined;
|
|
757
|
-
// Commit native lifecycle facts to the execution state before rendering/export can fail.
|
|
758
|
-
const finalHelperConfirmation = parseReadConfirmation(state.observedBrowserEffects?.readConfirmation);
|
|
759
|
-
if (finalHelperConfirmation?.state === "pending") {
|
|
760
|
-
confirmationFromHelper ||= state.observedBrowserEffects?.readConfirmation !== readConfirmationEvent;
|
|
761
|
-
readConfirmationEvent = finalHelperConfirmation;
|
|
762
|
-
succeeded = false;
|
|
763
|
-
}
|
|
764
|
-
applyBrowserRunStatePatch(state, { artifactManifest, freshSessionOrdinal, managedSessionActive, managedSessionCompatibilityWorkaround, managedSessionHeadedAutosaveDisabled, managedSessionHeadedAutosaveInterval, managedSessionCwd, managedSessionName, managedSessionNamespace, networkRoutesBySession });
|
|
765
|
-
state.observedBrowserEffects = {
|
|
766
|
-
args: prepared.redactedArgs, command: directClose ? "close" : prepared.executionPlan.commandInfo.command, subcommand: directClose ? undefined : prepared.executionPlan.commandInfo.subcommand,
|
|
767
|
-
sessionName: prepared.executionPlan.sessionName, namespace: prepared.executionPlan.namespace, sessionMode: prepared.sessionMode,
|
|
768
|
-
usedImplicitSession: prepared.executionPlan.usedImplicitSession, agentBrowserStarted: processResult.agentBrowserStarted,
|
|
769
|
-
nativeSucceeded: succeeded, managedSessionOutcome, managedSessionCwd: prepared.ownedManagedSessionContext?.cwd ?? managedSessionCwd, compatibilityWorkaround: prepared.compatibilityWorkaround,
|
|
770
|
-
managedSessionHeadedAutosaveDisabled: resultHeadedManagedAutosaveDisabled, managedSessionHeadedAutosaveInterval: resultHeadedManagedAutosaveInterval,
|
|
771
|
-
managedSessionRestoreDisabled: state.managedSessionRestoreState.isDisabled(prepared.executionPlan.sessionName, prepared.executionPlan.namespace),
|
|
772
|
-
closeAllApplied, readConfirmation: readConfirmationEvent ?? prepared.readConfirmation ?? state.observedBrowserEffects?.readConfirmation,
|
|
773
|
-
electron: electronLaunchRecord ? { launch: electronLaunchRecord, cleanup: electronFailedConnectCleanup } : undefined,
|
|
774
|
-
batchSteps: Array.isArray(presentationEnvelope?.data) ? presentationEnvelope.data.filter(isRecord).map(row => ({
|
|
775
|
-
command: Array.isArray(row.command) && row.command.every(token => typeof token === "string") ? isSuccessfulNativeConfirmedClose(row.command, row.result) ? ["close"] : redactInvocationArgs(row.command) : undefined,
|
|
776
|
-
success: row.success === true && !detectConfirmationRequired(row.result), lifecycle: extractAgentBrowserLifecycle(row.result),
|
|
777
|
-
})) : undefined,
|
|
778
|
-
};
|
|
779
|
-
let presentation = plainTextInspection ? { artifacts: undefined, batchFailure: undefined, batchSteps: undefined, content: [{ type: "text", text: inspectionText ?? "" }], data: undefined, fullOutputPath: undefined, fullOutputPaths: undefined, imagePath: undefined, imagePaths: undefined, savedFile: undefined, savedFilePath: undefined, summary: `${prepared.redactedArgs.join(" ")} completed` } : recordingStopRecovery && !recordingStopRecovery.batch ? recordingStopRecovery.presentation : await buildToolPresentation({ textOutput, stdin: prepared.processStdin, modelVisible: input.modelVisible, args: prepared.redactedProcessArgs, artifactManifest, artifactMaxUpdatedAtMs: Date.now(), artifactMinUpdatedAtMs: input.artifactRunStartedAtMs, artifactRequest: screenshotArtifactRequest, batchArtifactRequests: batchScreenshotArtifactRequests, commandInfo: { ...prepared.executionPlan.commandInfo, commandTokens: prepared.commandTokens }, compiledSemanticAction: prepared.compiledSemanticAction, cwd: operationCwd, envelope: presentationEnvelope, errorText, namespace: prepared.executionPlan.namespace, networkRouteDiagnostics, networkRoutes: activeNetworkRoutes, persistentArtifactStore, previousRecordingContactSheetPath: sessionStateKey ? state.activeRecordingReservations?.get(sessionStateKey)?.contactSheetPath : undefined, piCleanupOwnership: sessionStateKey && (state.ownedManagedSessions.has(sessionStateKey) || prepared.executionPlan.managedSessionName !== undefined) ? "wrapper-managed" : "caller-owned", sessionName: prepared.executionPlan.sessionName });
|
|
780
|
-
if (recordingStopRecovery)
|
|
781
|
-
presentation = mergeRecordingRecoveryPresentation(presentation, recordingStopRecovery);
|
|
782
|
-
if (parseError && processResult.exitCode !== 0 && processResult.stderr.trim() && !processResult.timedOut && !processResult.aborted && !processResult.spawnError) {
|
|
783
|
-
presentation.failureCategory = "upstream-error";
|
|
784
|
-
}
|
|
785
|
-
const confirmation = readConfirmationEvent ?? prepared.readConfirmation;
|
|
786
|
-
if (confirmation) {
|
|
787
|
-
presentation.readConfirmation = confirmation;
|
|
788
|
-
if (confirmation.state !== "cleared" || !detectConfirmationRequired(presentationEnvelope?.data)) {
|
|
789
|
-
presentation.nextActions = buildReadConfirmationNextActions(confirmation, readConfirmationEvent?.state === "pending");
|
|
790
|
-
}
|
|
791
|
-
if (readConfirmationEvent?.state === "pending") {
|
|
792
|
-
presentation.resultCategory = "failure";
|
|
793
|
-
presentation.failureCategory = "confirmation-required";
|
|
794
|
-
presentation.successCategory = undefined;
|
|
795
|
-
if (confirmationFromHelper)
|
|
796
|
-
presentation.content.unshift({ type: "text", text: `Native helper ${confirmation.command ?? "read"} requires confirmation (${confirmation.action ?? "read"}, ${confirmation.id}). The requested command's result, if dispatched, is preserved below.` });
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
if (plainTextUpgrade && !textOutput && !succeeded && typeof presentationEnvelope?.data === "string") {
|
|
800
|
-
presentation.data = presentationEnvelope.data;
|
|
801
|
-
const errorContent = presentation.content[0];
|
|
802
|
-
if (errorContent?.type === "text" && presentationEnvelope.data)
|
|
803
|
-
errorContent.text += `\n\n${presentationEnvelope.data}`;
|
|
804
|
-
if (input.modelVisible !== false)
|
|
805
|
-
presentation = await compactLargePresentationOutput({ artifactManifest, commandInfo: prepared.executionPlan.commandInfo, data: presentation.data, persistentArtifactStore, presentation });
|
|
806
|
-
}
|
|
807
|
-
if (electronHandoff?.error && electronHandoff.failureCategory)
|
|
808
|
-
presentation.failureCategory = electronHandoff.failureCategory;
|
|
809
|
-
networkRoutesBySession = applyBatchNetworkRouteState({ data: presentationEnvelope?.data, routesBySession: networkRoutesBySession, sessionName: sessionStateKey, succeeded });
|
|
810
|
-
if (presentation.resultCategory === "failure" && succeeded) {
|
|
811
|
-
succeeded = false;
|
|
812
|
-
presentationEnvelope = { ...(presentationEnvelope ?? {}), error: presentation.summary, success: false };
|
|
813
|
-
}
|
|
814
|
-
if (scrollNoopDiagnostic) {
|
|
815
|
-
succeeded = false;
|
|
816
|
-
presentation.resultCategory = "failure";
|
|
817
|
-
presentation.failureCategory = "upstream-error";
|
|
818
|
-
presentationEnvelope = { ...(presentationEnvelope ?? {}), error: "Scroll completed with no observed movement.", success: false };
|
|
819
|
-
presentation.summary = "Scroll completed with no observed movement.";
|
|
820
|
-
if (isRecord(presentation.data))
|
|
821
|
-
presentation.data = { ...presentation.data, noMovement: true, scrolled: false };
|
|
822
|
-
if (presentation.content[0]?.type === "text") {
|
|
823
|
-
const details = isRecord(presentation.data) ? JSON.stringify(omitUpstreamLifecycle(presentation.data), null, 2) : presentation.content[0].text;
|
|
824
|
-
presentation.content[0] = { ...presentation.content[0], text: `Scroll completed with no observed movement.\n\n${details}` };
|
|
825
|
-
}
|
|
826
|
-
else {
|
|
827
|
-
presentation.content.unshift({ type: "text", text: "Scroll completed with no observed movement." });
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
if (parseFailureOutput.artifactManifest) {
|
|
831
|
-
presentation.artifactManifest = parseFailureOutput.artifactManifest;
|
|
832
|
-
presentation.artifactRetentionSummary = parseFailureOutput.artifactRetentionSummary;
|
|
833
|
-
}
|
|
834
|
-
if (parseFailureOutput.fullOutputPath || parseFailureOutput.fullOutputUnavailable) {
|
|
835
|
-
const existingText = presentation.content[0]?.type === "text" ? presentation.content[0].text : "";
|
|
836
|
-
const noticeLines = [parseFailureOutput.fullOutputPath ? `Full output path: ${parseFailureOutput.fullOutputPath}` : `Full raw output unavailable: ${parseFailureOutput.fullOutputUnavailable}`, parseFailureOutput.artifactRetentionSummary].filter((item) => item !== undefined);
|
|
837
|
-
const notice = noticeLines.join("\n");
|
|
838
|
-
presentation.content[0] = { type: "text", text: existingText.length > 0 ? `${existingText}\n\n${notice}` : notice };
|
|
839
|
-
}
|
|
840
|
-
if (presentation.artifactManifest)
|
|
841
|
-
artifactManifest = presentation.artifactManifest;
|
|
842
|
-
const qaPreset = prepared.compiledQaPreset
|
|
843
|
-
? (processResult.timedOut ? analyzeQaPresetTimeout(prepared.compiledQaPreset) ?? analyzeQaPresetResults(presentationEnvelope?.data, prepared.compiledQaPreset) : analyzeQaPresetResults(presentationEnvelope?.data, prepared.compiledQaPreset))
|
|
844
|
-
: undefined;
|
|
845
|
-
if (qaPreset?.passed && presentation.resultCategory === "failure") {
|
|
846
|
-
qaPreset.passed = false;
|
|
847
|
-
qaPreset.summary = presentation.summary;
|
|
848
|
-
qaPreset.failedChecks.push(presentation.summary);
|
|
849
|
-
}
|
|
850
|
-
let qaAttachedTarget = prepared.compiledQaPreset?.checks.attached
|
|
851
|
-
? await collectQaAttachedTarget({ currentTarget: currentSessionTabTarget ?? prepared.priorSessionTabTarget, cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal })
|
|
852
|
-
: undefined;
|
|
853
|
-
const sourceLookupElectronContext = prepared.compiledSourceLookup ? getSourceLookupElectronContext({ currentTarget: currentSessionTabTarget, electronLaunchRecords, namespace: prepared.executionPlan.namespace, priorTarget: prepared.priorSessionTabTarget, sessionName: prepared.executionPlan.sessionName }) : undefined;
|
|
854
|
-
const sourceLookup = prepared.compiledSourceLookup ? await analyzeSourceLookupResults(presentationEnvelope?.data, prepared.compiledSourceLookup, operationCwd, { electronContext: sourceLookupElectronContext, workspaceRoot: operationCwd }) : undefined;
|
|
855
|
-
const networkSourceLookup = prepared.compiledNetworkSourceLookup ? redactNetworkSourceLookupAnalysis(await analyzeNetworkSourceLookupResults(presentationEnvelope?.data, prepared.compiledNetworkSourceLookup, operationCwd)) : undefined;
|
|
856
|
-
if (networkSourceLookup && presentation.content[0]?.type === "text")
|
|
857
|
-
presentation.content[0] = { ...presentation.content[0], text: `${networkSourceLookup.summary}\n\n${presentation.content[0].text}` };
|
|
858
|
-
else if (networkSourceLookup)
|
|
859
|
-
presentation.content.unshift({ type: "text", text: networkSourceLookup.summary });
|
|
860
|
-
if (sourceLookup && presentation.content[0]?.type === "text")
|
|
861
|
-
presentation.content[0] = { ...presentation.content[0], text: `${sourceLookup.summary}\n\n${presentation.content[0].text}` };
|
|
862
|
-
else if (sourceLookup)
|
|
863
|
-
presentation.content.unshift({ type: "text", text: sourceLookup.summary });
|
|
864
|
-
if (qaPreset && !qaPreset.passed && prepared.compiledQaPreset && presentation.failureCategory !== "artifact-missing") {
|
|
865
|
-
succeeded = false;
|
|
866
|
-
presentation.failureCategory = "qa-failure";
|
|
867
|
-
presentation.summary = qaPreset.summary;
|
|
868
|
-
const compactText = buildQaCompactFailureText({
|
|
869
|
-
causalError: presentation.batchFailure?.failedStep.text,
|
|
870
|
-
executedStepCount: presentation.batchSteps?.length,
|
|
871
|
-
page: extractQaPageContext({
|
|
872
|
-
attachedTarget: qaAttachedTarget,
|
|
873
|
-
batchData: presentationEnvelope?.data,
|
|
874
|
-
compiled: prepared.compiledQaPreset,
|
|
875
|
-
}),
|
|
876
|
-
plannedStepCount: prepared.compiledQaPreset.steps.length,
|
|
877
|
-
qaPreset,
|
|
878
|
-
});
|
|
879
|
-
const nonTextContent = presentation.content.filter((item) => item.type !== "text");
|
|
880
|
-
presentation.content = [{ type: "text", text: compactText }, ...nonTextContent];
|
|
881
|
-
}
|
|
882
|
-
else if (qaPreset?.passed && prepared.compiledQaPreset && succeeded) {
|
|
883
|
-
const compactText = buildQaCompactPassText({
|
|
884
|
-
artifactVerification: presentation.artifactVerification,
|
|
885
|
-
batchStepCount: presentation.batchSteps?.length ?? prepared.compiledQaPreset.steps.length,
|
|
886
|
-
checks: prepared.compiledQaPreset.checks,
|
|
887
|
-
page: extractQaPageContext({
|
|
888
|
-
attachedTarget: qaAttachedTarget,
|
|
889
|
-
batchData: presentationEnvelope?.data,
|
|
890
|
-
compiled: prepared.compiledQaPreset,
|
|
891
|
-
}),
|
|
892
|
-
qaPreset,
|
|
893
|
-
});
|
|
894
|
-
presentation.summary = qaPreset.summary;
|
|
895
|
-
const nonTextContent = presentation.content.filter((item) => item.type !== "text");
|
|
896
|
-
presentation.content = [{ type: "text", text: compactText }, ...nonTextContent];
|
|
897
|
-
}
|
|
898
|
-
const qaAttachedTargetText = formatQaAttachedTargetText(qaAttachedTarget);
|
|
899
|
-
const qaAttachedDiagnosticsText = prepared.compiledQaPreset?.checks.attached && prepared.compiledQaPreset.checks.diagnosticsResetAtStart === false && (prepared.compiledQaPreset.checks.checkNetwork || prepared.compiledQaPreset.checks.checkConsole || prepared.compiledQaPreset.checks.checkErrors)
|
|
900
|
-
? "Attached diagnostics: existing upstream session console/network/error buffers were preserved; rows may include events from before qa.attached started."
|
|
901
|
-
: undefined;
|
|
902
|
-
const qaAttachedBannerText = [qaAttachedTargetText, qaAttachedDiagnosticsText].filter((part) => typeof part === "string" && part.length > 0).join("\n");
|
|
903
|
-
const skipAttachedTargetBanner = qaPreset?.passed && prepared.compiledQaPreset?.checks.attached;
|
|
904
|
-
if (!skipAttachedTargetBanner && qaAttachedBannerText && presentation.content[0]?.type === "text")
|
|
905
|
-
presentation.content[0] = {
|
|
906
|
-
...presentation.content[0],
|
|
907
|
-
text: qaPreset?.passed === false
|
|
908
|
-
? `${presentation.content[0].text}\n\n${qaAttachedBannerText}`
|
|
909
|
-
: `${qaAttachedBannerText}\n\n${presentation.content[0].text}`,
|
|
910
|
-
};
|
|
911
|
-
else if (!skipAttachedTargetBanner && qaAttachedBannerText)
|
|
912
|
-
presentation.content.unshift({ type: "text", text: qaAttachedBannerText });
|
|
913
|
-
if (managedSessionOutcome && managedSessionOutcome.succeeded !== succeeded)
|
|
914
|
-
managedSessionOutcome = { ...managedSessionOutcome, succeeded };
|
|
915
|
-
const evalNavigationSummary = navigationSummary ?? extractNavigationSummaryFromData(presentationEnvelope?.data);
|
|
916
|
-
const evalSessionTabUrl = sessionStateKey ? sessionPageState.get(sessionStateKey).tabTarget?.url : undefined;
|
|
917
|
-
const evalPageUrl = evalNavigationSummary?.url ?? currentSessionTabTarget?.url ?? prepared.priorSessionTabTarget?.url ?? evalSessionTabUrl;
|
|
918
|
-
const evalStdinHint = getEvalStdinHint({ command: prepared.executionPlan.commandInfo.command, data: presentationEnvelope?.data, stdin: prepared.runtimeToolStdin });
|
|
919
|
-
const evalResultWarning = getEvalResultWarning({ command: prepared.executionPlan.commandInfo.command, data: presentationEnvelope?.data, navigationSummary: evalNavigationSummary, pageUrl: evalPageUrl, stdin: prepared.runtimeToolStdin });
|
|
920
|
-
if (readConfirmationEvent)
|
|
921
|
-
state.sessionPageState.applyReadConfirmation(readConfirmationEvent, sessionPageStateUpdate);
|
|
922
|
-
const resultArtifactManifest = presentation.artifactManifest ?? artifactManifest;
|
|
923
|
-
const artifactCleanup = await getArtifactCleanupGuidance({ command: prepared.executionPlan.commandInfo.command, cwd, manifest: resultArtifactManifest, succeeded });
|
|
924
|
-
const recordingTransitionReached = prepared.executionPlan.commandInfo.command === "batch"
|
|
925
|
-
? presentation.batchSteps?.some((step) => isRecordPageTransitionCommand(extractUpstreamCommandTokens(step.command ?? [])))
|
|
926
|
-
: isRecordPageTransitionCommand(prepared.commandTokens);
|
|
927
|
-
const recordingPageWarning = processResult.agentBrowserStarted && !prepared.executionPlan.plainTextInspection && recordingTransitionReached
|
|
928
|
-
? "Page state: this wrapper conservatively invalidates earlier refs after recording starts and URL-bearing restarts. Take a fresh snapshot before continuing; this does not prove the page changed."
|
|
929
|
-
: undefined;
|
|
930
|
-
const sessionWarning = electronPostCommandHealth ? formatElectronPostCommandHealthText(electronPostCommandHealth) : electronSessionMismatch ? formatElectronSessionMismatchText(electronSessionMismatch) : aboutBlankSessionMismatch ? buildAboutBlankWarning(aboutBlankSessionMismatch) : undefined;
|
|
931
|
-
const warningText = [sessionWarning, recordingPageWarning].filter(Boolean).join("\n\n") || undefined;
|
|
932
|
-
const redactedContent = input.modelVisible === false ? [] : buildRedactedPresentationContent({ exactSensitiveValues: prepared.exactSensitiveValues, plainTextInspection, presentation, presentationEnvelope, succeeded, userRequestedJson: prepared.userRequestedJson, warningText });
|
|
933
|
-
const finalRecoveryState = await prepareFinalResultRecoveryState({ aboutBlankSessionMismatch, batchRefSnapshotState, commandTokens: prepared.commandTokens, compiledSemanticAction: prepared.compiledSemanticAction, currentRefSnapshot, currentRefSnapshotInvalidation, currentSessionTabTarget, cwd, electronPostCommandHealth, errorText, executionPlan: prepared.executionPlan, parseError, plainTextInspection, presentation, processResult, redactedProcessArgs: prepared.redactedProcessArgs, runtimeToolArgs: prepared.runtimeToolArgs, sessionPageState, sessionPageStateUpdate, sessionTabCorrection, signal, succeeded });
|
|
934
|
-
currentRefSnapshot = finalRecoveryState.currentRefSnapshot;
|
|
935
|
-
currentRefSnapshotInvalidation = finalRecoveryState.currentRefSnapshotInvalidation;
|
|
936
|
-
const authoritativePageState = sessionStateKey ? sessionPageState.get(sessionStateKey) : undefined;
|
|
937
|
-
const newSnapshot = authoritativePageState?.refSnapshot && authoritativePageState.refSnapshot.snapshotId !== prepared.priorRefSnapshotState?.snapshotId;
|
|
938
|
-
const needsDaemonReceipt = prepared.ownedManagedSessionContext && !prepared.ownedManagedSessionContext.reuseOnly && !commandClosesSession && processResult.agentBrowserStarted
|
|
939
|
-
&& (succeeded || managedSessionOutcome?.activeAfter === true && managedSessionOutcome.currentSessionName === prepared.executionPlan.sessionName)
|
|
940
|
-
&& !state.managedSessionRestoreState.getDaemonReceipt(prepared.executionPlan.sessionName, prepared.executionPlan.namespace);
|
|
941
|
-
if (sessionStateKey && prepared.executionPlan.sessionName && (newSnapshot || needsDaemonReceipt)) {
|
|
942
|
-
const daemon = await inspectManagedSessionDaemon({ cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal, includeGeneration: true, headedManagedAutosaveInterval: prepared.ownedManagedSessionContext?.headedManagedAutosaveInterval ?? (prepared.ownedManagedSessionContext?.headedManagedAutosaveDisabled ? "0" : undefined), timeoutMs: prepared.processTimeoutMs });
|
|
943
|
-
if (newSnapshot) {
|
|
944
|
-
sessionPageState.bindSnapshotGeneration(sessionStateKey, daemon.status === "active" ? daemon.generation : undefined);
|
|
945
|
-
currentRefSnapshot = sessionPageState.get(sessionStateKey).refSnapshot;
|
|
946
|
-
}
|
|
947
|
-
if (prepared.ownedManagedSessionContext && daemon.status === "active" && daemon.generation) {
|
|
948
|
-
state.managedSessionRestoreState.recordDaemonRestoreKey(prepared.executionPlan.sessionName, prepared.executionPlan.namespace, daemon.restoreKey, daemon.generation);
|
|
949
|
-
}
|
|
950
|
-
}
|
|
951
|
-
if (sessionStateKey && currentRefSnapshot && processSucceeded && parseSucceeded && !unobservedMutation && readConfirmationEvent?.state === "cleared"
|
|
952
|
-
&& readConfirmationEvent.command === "snapshot" && readConfirmationEvent.action === "snapshot"
|
|
953
|
-
&& confirmedEffects.some(effect => effect.command === "snapshot" && effect.succeeded
|
|
954
|
-
&& effect.index === (Array.isArray(presentationEnvelope?.data) ? presentationEnvelope.data.length - 1 : 0) && extractRefSnapshotFromData(effect.data))) {
|
|
955
|
-
readConfirmationEvent = { ...readConfirmationEvent, refSnapshotFresh: true };
|
|
956
|
-
presentation.readConfirmation = readConfirmationEvent;
|
|
957
|
-
sessionPageState.applyReadConfirmation(readConfirmationEvent, sessionPageStateUpdate);
|
|
958
|
-
state.observedBrowserEffects = { ...state.observedBrowserEffects, readConfirmation: readConfirmationEvent };
|
|
959
|
-
}
|
|
960
|
-
if (sessionStateKey)
|
|
961
|
-
currentSessionTabTarget = authoritativePageState?.tabTarget;
|
|
962
|
-
const currentSessionTabTargetUnknown = authoritativePageState?.tabTargetUnknown === true ? true : undefined;
|
|
963
|
-
// ponytail: skip silent ref copies; direct failure receipts need their existing fields until final publication owns those paths.
|
|
964
|
-
const result = buildFinalAgentBrowserToolResult({ modelVisible: input.modelVisible, aboutBlankSessionMismatch, artifactCleanup, categoryDetails: finalRecoveryState.categoryDetails, clickDispatchDiagnostic, commandTokens: prepared.commandTokens, comboboxFocusDiagnostic, compiledNetworkSourceLookup: prepared.compiledNetworkSourceLookup, compiledSemanticAction: prepared.compiledSemanticAction, compatibilityWorkaround: prepared.compatibilityWorkaround, currentRefSnapshot: input.modelVisible === false ? undefined : currentRefSnapshot, currentRefSnapshotInvalidation, currentSessionTabTarget, currentSessionTabTargetUnknown, electronBroadGetTextScopeDiagnostics, electronFailedConnectCleanup, electronHandoff, electronLaunch: prepared.electronLaunch, electronLaunchRecord, electronLaunchRecords, electronPostCommandHealth, electronProfileIsolationDetails: input.electronProfileIsolationDetails, electronRefFreshnessDiagnostic, electronSessionMismatch, errorText, evalResultWarning, evalStdinHint, exactSensitiveValues: prepared.exactSensitiveValues, executionPlan: prepared.executionPlan, fillVerificationDiagnostic, headedLaunch: prepared.headedLaunch, inspectionText, preserveAttachedBrowserSession: input.preserveAttachedBrowserSession === true, providerLaunch: prepared.providerLaunch, managedSessionHeadedAutosaveDisabled: !prepared.ownedManagedSessionContext?.reuseOnly && resultHeadedManagedAutosaveDisabled || undefined, managedSessionHeadedAutosaveInterval: prepared.ownedManagedSessionContext?.reuseOnly ? undefined : resultHeadedManagedAutosaveInterval, managedSessionOutcome, managedSessionRestoreDisabled: state.managedSessionRestoreState.isDisabled(prepared.executionPlan.sessionName, prepared.executionPlan.namespace), navigationSummary, networkSourceLookup, noActivePageSnapshotFailure: finalRecoveryState.noActivePageSnapshotFailure, openResultTabCorrection, overlayBlockerDiagnostic, parseError, parseFailureOutput, parseSucceeded, plainTextInspection, presentation, presentationEnvelope, priorSessionTabTarget: prepared.priorSessionTabTarget, processResult, qaAttachedTarget, qaPreset, recordingDependencyWarning, redactedArgs: prepared.redactedArgs, redactedCompiledElectron: prepared.redactedCompiledElectron, redactedCompiledJob: prepared.redactedCompiledJob, redactedCompiledNetworkSourceLookup: prepared.redactedCompiledNetworkSourceLookup, redactedCompiledQaPreset: prepared.redactedCompiledQaPreset, redactedCompiledSemanticAction: prepared.redactedCompiledSemanticAction, redactedCompiledSourceLookup: prepared.redactedCompiledSourceLookup, redactedContent, redactedProcessArgs: prepared.redactedProcessArgs, redactedRecoveryHint: prepared.redactedRecoveryHint, resultArtifactManifest, richInputRecoveryDiagnostic: finalRecoveryState.richInputRecoveryDiagnostic, scrollNoopDiagnostic, selectorTextVisibilityDiagnostics, sessionMode: prepared.sessionMode, sessionTabCorrection, sourceLookup, succeeded, timeoutPartialProgress, unsettledWebMcpMutation, userRequestedJson: prepared.userRequestedJson, visibleRefFallbackDiagnostic: finalRecoveryState.visibleRefFallbackDiagnostic, visibleRefFallbackSessionName: finalRecoveryState.visibleRefFallbackSessionName });
|
|
965
|
-
const resultWithCloseAll = closeAllApplied
|
|
966
|
-
? { ...result, details: { ...(isRecord(result.details) ? result.details : {}), closeAllApplied: true } }
|
|
967
|
-
: result;
|
|
968
|
-
const statePatch = { artifactManifest, freshSessionOrdinal, managedSessionActive, managedSessionCompatibilityWorkaround, managedSessionHeadedAutosaveDisabled, managedSessionHeadedAutosaveInterval, managedSessionCwd, managedSessionName, managedSessionNamespace, networkRoutesBySession };
|
|
969
|
-
return { result: resultWithCloseAll, statePatch };
|
|
11
|
+
const native = await observeNativeEffects(input, ownership);
|
|
12
|
+
const page = await observePageEffects(input, native);
|
|
13
|
+
const lifecycle = await commitLifecycleEffects(input, native, page, ownership);
|
|
14
|
+
const { publication, recovery } = await publishOutputEffects(input, native, page, lifecycle);
|
|
15
|
+
return buildOutputResult({ input, native, page, lifecycle, publication }, recovery);
|
|
970
16
|
}
|
|
971
17
|
finally {
|
|
972
|
-
|
|
973
|
-
|
|
18
|
+
const path = input.processResult.stdoutSpillPath;
|
|
19
|
+
if (path !== undefined && path.length > 0) {
|
|
20
|
+
await rm(path, { force: true }).catch(() => {
|
|
21
|
+
// This raw spool is disposable and may already be removed; cleanup must not replace the native outcome or a publication failure.
|
|
22
|
+
});
|
|
23
|
+
}
|
|
974
24
|
}
|
|
975
25
|
}
|