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,1067 +1,163 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { extractUpstreamCommandTokens, findCommandStartIndex, parseArgvDescriptor, parseCommandInfo, } from "./argv-descriptor.js";
|
|
4
|
-
import { batchHasSuccessfulCloseAll, getSuccessfulBatchCloseLifecycle } from "./batch-lifecycle.js";
|
|
5
|
-
import { getBrowserResultMessage } from "./browser-transcript.js";
|
|
6
|
-
import { canonicalizeAgentBrowserNamespace, extractExplicitNamespace, extractExplicitSessionName, getAgentBrowserSessionIdentityKey, getBooleanFlagValue, GLOBAL_BOOLEAN_FLAGS_WITH_OPTIONAL_VALUES, GLOBAL_VALUE_FLAGS_ALLOWING_DASH_VALUE, isAgentBrowserSessionIdentityKeyInNamespace, isUpstreamEnvFlagEnabled, PREVALIDATED_VALUE_FLAGS, projectUpstreamGlobalFlags, resolveAgentBrowserNamespace, scanUpstreamGlobalFlagOccurrences, stripUpstreamGlobalFlags, } from "./argv-grammar.js";
|
|
1
|
+
import { parseArgvDescriptor } from "./argv-descriptor.js";
|
|
2
|
+
import { canonicalizeAgentBrowserNamespace, extractExplicitNamespace, extractExplicitSessionName, getAgentBrowserSessionIdentityKey, getBooleanFlagValue, scanUpstreamGlobalFlagOccurrences, } from "./argv-grammar.js";
|
|
7
3
|
import { needsManagedSession } from "./command-policy.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { hasLaunchScopedFlagToken, LAUNCH_SCOPED_FLAG_DEFINITIONS, LAUNCH_SCOPED_FLAG_LABEL, } from "./launch-scoped-flags.js";
|
|
11
|
-
import { MANAGED_SESSION_NAME_PREFIX, } from "./managed-session-restore.js";
|
|
12
|
-
export { extractCommandTokens, extractUpstreamCommandTokens, findCommandStartIndex, parseArgvDescriptor, parseCommandInfo, parseWaitCommandTokens } from "./argv-descriptor.js";
|
|
13
|
-
import { isRecord } from "./parsing.js";
|
|
4
|
+
import { isCloseCommand } from "./command-taxonomy.js";
|
|
5
|
+
import { hasLaunchScopedFlagToken, LAUNCH_SCOPED_FLAG_DEFINITIONS } from "./launch-scoped-flags.js";
|
|
14
6
|
import { getAgentBrowserProcessEnvironment } from "./process-environment.js";
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const AUTH_STATE_QUERY_PARAM_PATTERN = /^(?:nonce|state)$/i;
|
|
29
|
-
const AUTH_URL_CONTEXT_PATTERN = /(?:^|[./_-])(?:auth|authorize|callback|login|oauth2?|oidc|saml|sso)(?:[./?#_-]|$)/i;
|
|
30
|
-
const SENSITIVE_FIELD_NAME_PATTERN = /^(?:[A-Za-z0-9_-]*(?:api[_-]?key|access[_-]?key|private[_-]?key|secret(?:[_-]?(?:key|access[_-]?key))?|token|password|passwd|credentials?|database[_-]?url|db[_-]?url|connection[_-]?string|mongo(?:db)?[_-]?uri|redis[_-]?url)|[A-Za-z0-9]*(?:apiKey|ApiKey|apikey|privateKey|PrivateKey|databaseUrl|DatabaseUrl|dbUrl|DbUrl|connectionString|ConnectionString|mongoUri|MongoUri|mongodbUri|MongodbUri|mongoDbUri|MongoDbUri|redisUrl|RedisUrl|Token|Secret|Password|Credential|Credentials)|auth(?:orization)?|bearer|client(?:_|-)?secret|cookie|id(?:_|-)?token|pass(?:word)?|proxy(?:_|-)?authorization|refresh(?:_|-)?token|sentry(?:_|-)?key|session(?:_|-)?id|set(?:_|-)?cookie|sig(?:nature)?|write(?:_|-)?key|x(?:_|-)?api(?:_|-)?key)$/i;
|
|
31
|
-
const ENV_SECRET_ASSIGNMENT_PATTERN = /\b((?:export\s+)?([A-Za-z_][A-Za-z0-9_-]*)(\s*[:=]\s*))(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|[^\s,;]+)/g;
|
|
32
|
-
const DEFAULT_HEADLESS_COMPAT_USER_AGENT_BY_PLATFORM = {
|
|
33
|
-
darwin: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
34
|
-
linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
35
|
-
win32: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
|
|
36
|
-
};
|
|
37
|
-
const FALLBACK_HEADLESS_COMPAT_USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36";
|
|
38
|
-
const SHELL_OPERATOR_TOKENS = new Set(["&&", "||", "|", ";", ">", ">>", "<"]);
|
|
39
|
-
const ANDROID_SESSION_NAME_IDENTITY_LENGTH = 20;
|
|
40
|
-
const MAX_PROJECT_SLUG_LENGTH = 24;
|
|
41
|
-
const SESSION_NAME_CWD_HASH_LENGTH = 8;
|
|
42
|
-
const SESSION_NAME_SESSION_ID_LENGTH = 12;
|
|
43
|
-
function isStringArray(value) {
|
|
44
|
-
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
45
|
-
}
|
|
46
|
-
function shouldRedactQueryParam(name) {
|
|
47
|
-
return SENSITIVE_QUERY_PARAM_PATTERN.test(name) || isSensitiveFieldName(name);
|
|
48
|
-
}
|
|
49
|
-
function redactUrlToken(token) {
|
|
50
|
-
let parsed;
|
|
51
|
-
try {
|
|
52
|
-
parsed = new URL(token);
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
return token;
|
|
56
|
-
}
|
|
57
|
-
const originalHref = parsed.href;
|
|
58
|
-
if (parsed.username.length > 0)
|
|
59
|
-
parsed.username = "[REDACTED]";
|
|
60
|
-
if (parsed.password.length > 0)
|
|
61
|
-
parsed.password = "[REDACTED]";
|
|
62
|
-
const hashText = parsed.hash.startsWith("#") ? parsed.hash.slice(1) : parsed.hash;
|
|
63
|
-
const hashParams = hashText.includes("=") ? new URLSearchParams(hashText) : undefined;
|
|
64
|
-
const authContext = AUTH_URL_CONTEXT_PATTERN.test(`${parsed.hostname}${parsed.pathname}`)
|
|
65
|
-
|| [...parsed.searchParams.keys(), ...(hashParams?.keys() ?? [])].some(shouldRedactQueryParam);
|
|
66
|
-
for (const [name] of parsed.searchParams) {
|
|
67
|
-
if (shouldRedactQueryParam(name) || (authContext && AUTH_STATE_QUERY_PARAM_PATTERN.test(name))) {
|
|
68
|
-
parsed.searchParams.set(name, "[REDACTED]");
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (hashParams) {
|
|
72
|
-
let hashMutated = false;
|
|
73
|
-
for (const [name] of hashParams) {
|
|
74
|
-
if (shouldRedactQueryParam(name) || (authContext && AUTH_STATE_QUERY_PARAM_PATTERN.test(name))) {
|
|
75
|
-
hashParams.set(name, "[REDACTED]");
|
|
76
|
-
hashMutated = true;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (hashMutated)
|
|
80
|
-
parsed.hash = `#${hashParams.toString()}`;
|
|
81
|
-
}
|
|
82
|
-
return parsed.href === originalHref ? token : parsed.href;
|
|
83
|
-
}
|
|
84
|
-
function redactLooseUrlParameterText(text) {
|
|
85
|
-
return text.replace(/(?<![^\s"'`<>\])}])[^\s"'`<>\])}]*[?#&][^\s"'`<>\])}]*/g, (token) => {
|
|
86
|
-
const queryNames = [...token.matchAll(/[?#&]([^=&#\s"'`<>\])}]+)=/g)].map((match) => {
|
|
87
|
-
try {
|
|
88
|
-
return decodeURIComponent((match[1] ?? "").replace(/\+/g, " "));
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
return match[1] ?? "";
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
const authContext = AUTH_URL_CONTEXT_PATTERN.test(token) || queryNames.some(shouldRedactQueryParam);
|
|
95
|
-
return token.replace(/([?#&])([^=&#\s"'`<>\])}]+)=([^&#\s"'`<>\])}]*)/g, (match, separator, rawName, rawValue) => {
|
|
96
|
-
if (rawValue === "[REDACTED" || rawValue === "[REDACTED]" || /%5Bredacted%5D/i.test(rawValue))
|
|
97
|
-
return match;
|
|
98
|
-
let name = rawName;
|
|
99
|
-
try {
|
|
100
|
-
name = decodeURIComponent(rawName.replace(/\+/g, " "));
|
|
101
|
-
}
|
|
102
|
-
catch {
|
|
103
|
-
// Keep the raw name when percent decoding fails.
|
|
104
|
-
}
|
|
105
|
-
if (!shouldRedactQueryParam(name) && !(authContext && AUTH_STATE_QUERY_PARAM_PATTERN.test(name)))
|
|
106
|
-
return match;
|
|
107
|
-
return `${separator}${rawName}=[REDACTED]`;
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
function redactLooseUrlUserinfo(text) {
|
|
112
|
-
return text.replace(/\b([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^\s"'`/@]+)@([^\s"'`]+)/g, (match, prefix, userinfo, suffix) => {
|
|
113
|
-
if (/%5Bredacted%5D/i.test(userinfo))
|
|
114
|
-
return match;
|
|
115
|
-
if (userinfo.includes("[REDACTED]"))
|
|
116
|
-
return redactLooseUrlParameterText(match);
|
|
117
|
-
return redactLooseUrlParameterText(`${prefix}${userinfo.includes(":") ? "[REDACTED]:[REDACTED]" : "[REDACTED]"}@${suffix}`);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
function redactLooseUrlMatches(text) {
|
|
121
|
-
return text.replace(/\b[A-Za-z][A-Za-z0-9+.-]*:\/\/[^\s"'`<>\])]+/g, (match) => redactUrlToken(match));
|
|
122
|
-
}
|
|
123
|
-
function createBalancedJsonEndFinder(text) {
|
|
124
|
-
let boundaries;
|
|
125
|
-
return (startIndex) => {
|
|
126
|
-
const opener = text[startIndex];
|
|
127
|
-
if (opener !== "{" && opener !== "[")
|
|
128
|
-
return undefined;
|
|
129
|
-
if (!boundaries) {
|
|
130
|
-
// Resolve each suffix once: skip strings and balanced groups to its first unmatched closer.
|
|
131
|
-
boundaries = new Int32Array(text.length + 1).fill(-1);
|
|
132
|
-
let quoteAtNext = -1;
|
|
133
|
-
let quoteAfterNext = -1;
|
|
134
|
-
for (let index = text.length - 1; index >= 0; index -= 1) {
|
|
135
|
-
const char = text[index];
|
|
136
|
-
if (char === "}" || char === "]") {
|
|
137
|
-
boundaries[index] = index;
|
|
138
|
-
}
|
|
139
|
-
else if (char === '"') {
|
|
140
|
-
boundaries[index] = quoteAtNext < 0 ? -1 : boundaries[quoteAtNext + 1];
|
|
141
|
-
}
|
|
142
|
-
else if (char === "{" || char === "[") {
|
|
143
|
-
const end = boundaries[index + 1];
|
|
144
|
-
boundaries[index] = end >= 0 && text[end] === (char === "{" ? "}" : "]") ? boundaries[end + 1] : -1;
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
boundaries[index] = boundaries[index + 1];
|
|
148
|
-
}
|
|
149
|
-
// Inside a string, backslash skips one character; outside, it is ordinary text.
|
|
150
|
-
const quote = char === '"' ? index : char === "\\" ? quoteAfterNext : quoteAtNext;
|
|
151
|
-
quoteAfterNext = quoteAtNext;
|
|
152
|
-
quoteAtNext = quote;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
const end = boundaries[startIndex + 1];
|
|
156
|
-
return end >= 0 && text[end] === (opener === "{" ? "}" : "]") ? end : undefined;
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
function redactSerializedJson(text) {
|
|
160
|
-
if (text === "[REDACTED]")
|
|
161
|
-
return undefined;
|
|
162
|
-
if (!/^\s*[\[{"\d\-tfn]/.test(text))
|
|
163
|
-
return undefined;
|
|
164
|
-
// Validate grammar only; rebuilding parsed values loses duplicates and numeric spelling.
|
|
165
|
-
try {
|
|
166
|
-
JSON.parse(text);
|
|
167
|
-
}
|
|
168
|
-
catch {
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
let output = "";
|
|
172
|
-
let cursor = 0;
|
|
173
|
-
const findEnd = createBalancedJsonEndFinder(text);
|
|
174
|
-
const strings = /"(?:\\.|[^"\\])*"/g;
|
|
175
|
-
let match;
|
|
176
|
-
while ((match = strings.exec(text)) !== null) {
|
|
177
|
-
const end = strings.lastIndex;
|
|
178
|
-
const value = JSON.parse(match[0]);
|
|
179
|
-
const redacted = redactSensitiveText(value);
|
|
180
|
-
if (redacted !== value) {
|
|
181
|
-
output += text.slice(cursor, match.index) + JSON.stringify(redacted);
|
|
182
|
-
cursor = end;
|
|
183
|
-
}
|
|
184
|
-
const separator = /^\s*:\s*/.exec(text.slice(end));
|
|
185
|
-
if (!separator || !isSensitiveFieldName(value))
|
|
186
|
-
continue;
|
|
187
|
-
const valueStart = end + separator[0].length;
|
|
188
|
-
let valueEnd = findEnd(valueStart);
|
|
189
|
-
if (valueEnd !== undefined) {
|
|
190
|
-
valueEnd += 1;
|
|
191
|
-
}
|
|
192
|
-
else if (text[valueStart] === '"') {
|
|
193
|
-
strings.lastIndex = valueStart;
|
|
194
|
-
const fieldValue = strings.exec(text);
|
|
195
|
-
valueEnd = strings.lastIndex;
|
|
196
|
-
if (JSON.parse(fieldValue[0]) === "[REDACTED]")
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
valueEnd = valueStart;
|
|
201
|
-
while (valueEnd < text.length && !/[\s,\]}]/.test(text[valueEnd]))
|
|
202
|
-
valueEnd += 1;
|
|
203
|
-
}
|
|
204
|
-
output += text.slice(cursor, valueStart) + '"[REDACTED]"';
|
|
205
|
-
cursor = valueEnd;
|
|
206
|
-
strings.lastIndex = valueEnd;
|
|
207
|
-
}
|
|
208
|
-
return output + text.slice(cursor);
|
|
209
|
-
}
|
|
210
|
-
function redactEmbeddedStructuredText(text) {
|
|
211
|
-
let output = "";
|
|
212
|
-
let cursor = 0;
|
|
213
|
-
const findEnd = createBalancedJsonEndFinder(text);
|
|
214
|
-
while (cursor < text.length) {
|
|
215
|
-
const char = text[cursor];
|
|
216
|
-
if (char !== "{" && char !== "[") {
|
|
217
|
-
output += char;
|
|
218
|
-
cursor += 1;
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
const endIndex = findEnd(cursor);
|
|
222
|
-
if (endIndex === undefined) {
|
|
223
|
-
output += char;
|
|
224
|
-
cursor += 1;
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
const candidate = text.slice(cursor, endIndex + 1);
|
|
228
|
-
output += redactSerializedJson(candidate) ?? candidate;
|
|
229
|
-
cursor = endIndex + 1;
|
|
230
|
-
}
|
|
231
|
-
return output;
|
|
232
|
-
}
|
|
233
|
-
function redactStandaloneBasicCredential(text) {
|
|
234
|
-
return text.replace(/\b(Basic)\s+([A-Za-z0-9+/=]{12,})/gi, (match, label, credential) => {
|
|
235
|
-
if (!/[0-9+/=]/.test(credential))
|
|
236
|
-
return match;
|
|
237
|
-
return `${label} [REDACTED]`;
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
function credentialTrailingPunctuation(credential) {
|
|
241
|
-
return credential.match(/[,.:;!?]+$/)?.[0] ?? "";
|
|
242
|
-
}
|
|
243
|
-
function formatRedactedCredential(label, credential, trailing = "") {
|
|
244
|
-
return `${label} [REDACTED]${credentialTrailingPunctuation(credential)}${trailing}`;
|
|
245
|
-
}
|
|
246
|
-
function redactBearerCredentials(text) {
|
|
247
|
-
return text
|
|
248
|
-
.replace(/((?:\b([A-Za-z][A-Za-z0-9_-]*)\s*[:=]\s*|(?:^|\s)(?:-H\s*|--header(?:\s+|=)))["']?Bearer)\s+([^\s"',)\[\]]+)([),.]?)/gi, (match, label, field, credential, trailing) => {
|
|
249
|
-
if (field && !isSensitiveFieldName(field))
|
|
250
|
-
return match;
|
|
251
|
-
return formatRedactedCredential(label, credential, trailing);
|
|
252
|
-
})
|
|
253
|
-
.replace(/\b(Bearer)\s+([^\s\\"',)\[\]]+)([),.]?)/gi, (match, label, credential, trailing) => {
|
|
254
|
-
// Without a credential field/header, require a bearer-token shape, not prose, HTML or a URL.
|
|
255
|
-
const token = credential.slice(0, credential.length - credentialTrailingPunctuation(credential).length);
|
|
256
|
-
if (!/^[A-Za-z0-9._~+/-]+=*$/.test(token) || !/[0-9._~+/=-]/.test(token))
|
|
257
|
-
return match;
|
|
258
|
-
return formatRedactedCredential(label, credential, trailing);
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
function isSensitiveFieldName(key) {
|
|
262
|
-
SENSITIVE_FIELD_NAME_PATTERN.lastIndex = 0;
|
|
263
|
-
return SENSITIVE_FIELD_NAME_PATTERN.test(key);
|
|
264
|
-
}
|
|
265
|
-
function isEnvSecretAssignmentKey(key) {
|
|
266
|
-
if (!isSensitiveFieldName(key))
|
|
267
|
-
return false;
|
|
268
|
-
if (key === "password" || key.includes("_") || key.includes("-") || key === key.toUpperCase())
|
|
269
|
-
return true;
|
|
270
|
-
return /(?:apiKey|ApiKey|privateKey|PrivateKey|databaseUrl|DatabaseUrl|dbUrl|DbUrl|connectionString|ConnectionString|mongoUri|MongoUri|mongodbUri|MongodbUri|mongoDbUri|MongoDbUri|redisUrl|RedisUrl|Token|Secret|Password|Credential|Credentials)$/.test(key);
|
|
271
|
-
}
|
|
272
|
-
function redactEnvSecretAssignments(text) {
|
|
273
|
-
return text.replace(ENV_SECRET_ASSIGNMENT_PATTERN, (match, prefix, key, _separator, offset) => {
|
|
274
|
-
if (!isEnvSecretAssignmentKey(key))
|
|
275
|
-
return match;
|
|
276
|
-
if (key === "password") {
|
|
277
|
-
// The loose matcher cannot safely distinguish inline punctuation from password characters.
|
|
278
|
-
const end = offset + match.length;
|
|
279
|
-
if ((offset > 0 && text[offset - 1] !== "\n" && text[offset - 1] !== "\r")
|
|
280
|
-
|| (end < text.length && text[end] !== "\n" && text[end] !== "\r")
|
|
281
|
-
|| /^(?:\[REDACTED\]|%5Bredacted%5D)/i.test(match.slice(prefix.length)))
|
|
282
|
-
return match;
|
|
283
|
-
const value = match.slice(prefix.length);
|
|
284
|
-
const boundary = value[0] === '"' || value[0] === "'" ? -1 : value.search(/[&#](?=[A-Za-z_][A-Za-z0-9_-]*\s*=)/);
|
|
285
|
-
return `${prefix}[REDACTED]${boundary < 0 ? "" : value.slice(boundary)}`;
|
|
286
|
-
}
|
|
287
|
-
return `${prefix}[REDACTED]`;
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
export function redactSensitiveText(text) {
|
|
291
|
-
// Redact JSON string literals before text heuristics can consume their escapes.
|
|
292
|
-
// Non-JSON stays whole so assignments and headers retain their credential context.
|
|
293
|
-
const serialized = redactSerializedJson(text);
|
|
294
|
-
if (serialized !== undefined)
|
|
295
|
-
return serialized;
|
|
296
|
-
const embeddedRedactedText = redactEmbeddedStructuredText(text);
|
|
297
|
-
return redactEmbeddedStructuredText(redactEnvSecretAssignments(redactStandaloneBasicCredential(redactBearerCredentials(redactLooseUrlParameterText(redactLooseUrlUserinfo(redactLooseUrlMatches(embeddedRedactedText))))
|
|
298
|
-
.replace(/\b(Authorization\s*:\s*Basic)\s+[^\s",]+/gi, "$1 [REDACTED]")
|
|
299
|
-
.replace(/\b(Cookie|Set-Cookie)\s*:\s*[^\n\r"]+/gi, "$1: [REDACTED]"))));
|
|
300
|
-
}
|
|
301
|
-
export function redactSensitiveValue(value) {
|
|
302
|
-
if (typeof value === "string") {
|
|
303
|
-
return redactSensitiveText(value);
|
|
304
|
-
}
|
|
305
|
-
if (Array.isArray(value)) {
|
|
306
|
-
return value.map((item) => redactSensitiveValue(item));
|
|
307
|
-
}
|
|
308
|
-
if (!isRecord(value)) {
|
|
309
|
-
return value;
|
|
310
|
-
}
|
|
311
|
-
return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => {
|
|
312
|
-
if (isSensitiveFieldName(key)) {
|
|
313
|
-
return [key, "[REDACTED]"];
|
|
314
|
-
}
|
|
315
|
-
return [key, redactSensitiveValue(entryValue)];
|
|
316
|
-
}));
|
|
317
|
-
}
|
|
318
|
-
function redactFlagValue(flag, value) {
|
|
319
|
-
if (SENSITIVE_VALUE_FLAGS.has(flag)) {
|
|
320
|
-
return "[REDACTED]";
|
|
321
|
-
}
|
|
322
|
-
return redactUrlToken(value);
|
|
323
|
-
}
|
|
324
|
-
export function redactInvocationArgs(args) {
|
|
325
|
-
const redacted = [];
|
|
326
|
-
let pendingValueFlag;
|
|
327
|
-
for (const token of args) {
|
|
328
|
-
if (pendingValueFlag) {
|
|
329
|
-
redacted.push(redactFlagValue(pendingValueFlag, token));
|
|
330
|
-
pendingValueFlag = undefined;
|
|
331
|
-
continue;
|
|
332
|
-
}
|
|
333
|
-
const normalizedToken = token.split("=", 1)[0] ?? token;
|
|
334
|
-
if (SENSITIVE_VALUE_FLAGS.has(normalizedToken)) {
|
|
335
|
-
if (token.includes("=")) {
|
|
336
|
-
redacted.push(`${normalizedToken}=[REDACTED]`);
|
|
337
|
-
}
|
|
338
|
-
else {
|
|
339
|
-
redacted.push(token);
|
|
340
|
-
pendingValueFlag = normalizedToken;
|
|
341
|
-
}
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
redacted.push(redactSensitiveText(redactUrlToken(token)));
|
|
345
|
-
}
|
|
346
|
-
const commandStartIndex = findCommandStartIndex(args);
|
|
347
|
-
if (commandStartIndex !== undefined && args[commandStartIndex] === "set" && args[commandStartIndex + 1] === "credentials") {
|
|
348
|
-
for (const index of [commandStartIndex + 2, commandStartIndex + 3]) {
|
|
349
|
-
if (redacted[index] !== undefined) {
|
|
350
|
-
redacted[index] = "[REDACTED]";
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
if (commandStartIndex !== undefined && args[commandStartIndex] === "cookies" && args[commandStartIndex + 1] === "set"
|
|
355
|
-
&& !extractUpstreamCommandTokens(args).slice(2).includes("--curl")
|
|
356
|
-
&& redacted[commandStartIndex + 3] !== undefined) {
|
|
357
|
-
redacted[commandStartIndex + 3] = "[REDACTED]";
|
|
358
|
-
}
|
|
359
|
-
if (commandStartIndex !== undefined
|
|
360
|
-
&& args[commandStartIndex] === "storage"
|
|
361
|
-
&& ["local", "session"].includes(args[commandStartIndex + 1] ?? "")
|
|
362
|
-
&& args[commandStartIndex + 2] === "set"
|
|
363
|
-
&& redacted[commandStartIndex + 4] !== undefined) {
|
|
364
|
-
redacted[commandStartIndex + 4] = "[REDACTED]";
|
|
365
|
-
}
|
|
366
|
-
if (commandStartIndex !== undefined && args[commandStartIndex] === "clipboard" && args[commandStartIndex + 1] === "write") {
|
|
367
|
-
for (let index = commandStartIndex + 2; index < redacted.length; index += 1) {
|
|
368
|
-
redacted[index] = "[REDACTED]";
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
const batch = projectUpstreamGlobalFlags(args);
|
|
372
|
-
if (batch.tokens[0] === "batch") {
|
|
373
|
-
for (let index = 1; index < batch.tokens.length; index++) {
|
|
374
|
-
if (batch.tokens[index] === "--bail")
|
|
375
|
-
continue;
|
|
376
|
-
const step = parseBatchCommandArgument(batch.tokens[index]).step;
|
|
377
|
-
if (!step)
|
|
378
|
-
continue;
|
|
379
|
-
const safe = redactInvocationArgs(step);
|
|
380
|
-
if (safe.some((token, offset) => token !== step[offset]))
|
|
381
|
-
redacted[batch.indices[index]] = safe.map(token => `'${token.replaceAll("'", "'\\''")}'`).join(" ");
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return redacted;
|
|
385
|
-
}
|
|
386
|
-
export function isPlainTextInspectionArgs(args) {
|
|
387
|
-
return args.some((token) => INSPECTION_FLAGS.has(token));
|
|
7
|
+
import { formatInvalidValueFlagError, getInvalidValueFlagDetails, isPlainTextInspectionArgs, } from "./runtime-args-validation.js";
|
|
8
|
+
import { canUseHeadlessCompatibilityUserAgent, getCompatibilityWorkaround, getDefaultHeadlessCompatUserAgent, } from "./runtime-compatibility.js";
|
|
9
|
+
import { freshSessionRecoveryHint, launchFlagsRecoveryReason, selectExecutionSession, stripExplicitIdentityArgs, } from "./runtime-session-plan.js";
|
|
10
|
+
export { extractCommandTokens, extractUpstreamCommandTokens, findCommandStartIndex, parseArgvDescriptor, parseCommandInfo, parseWaitCommandTokens, } from "./argv-descriptor.js";
|
|
11
|
+
export { redactSensitiveText, redactSensitiveValue, redactInvocationArgs, } from "./runtime-redaction.js";
|
|
12
|
+
export { getImplicitSessionIdleTimeoutMs, getImplicitSessionCloseTimeoutMs, } from "./runtime-timeouts.js";
|
|
13
|
+
export { isPlainTextInspectionArgs, validateToolArgs } from "./runtime-args-validation.js";
|
|
14
|
+
export { canUseHeadlessCompatibilityUserAgent, getDefaultHeadlessCompatUserAgent, } from "./runtime-compatibility.js";
|
|
15
|
+
export { createEphemeralSessionSeed, createImplicitSessionName, createFreshSessionName, isRestorableManagedSessionName, resolveManagedSessionState, } from "./runtime-session-identity.js";
|
|
16
|
+
export { restoreManagedSessionStateFromBranch } from "./runtime-session-replay.js";
|
|
17
|
+
export { chooseOpenResultTabCorrection } from "./runtime-tab-correction.js";
|
|
18
|
+
export function getStartupScopedFlags(args) {
|
|
19
|
+
return LAUNCH_SCOPED_FLAG_DEFINITIONS.map((definition) => definition.flag).filter((flag) => hasLaunchScopedFlagToken(args, flag));
|
|
388
20
|
}
|
|
389
|
-
function
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
return
|
|
395
|
-
const parsedValue = Number(normalizedValue);
|
|
396
|
-
if (!Number.isSafeInteger(parsedValue) || parsedValue < minimumValue) {
|
|
397
|
-
return undefined;
|
|
21
|
+
function withNativeSession(args) {
|
|
22
|
+
const nativeSession = getAgentBrowserProcessEnvironment().AGENT_BROWSER_SESSION;
|
|
23
|
+
if (nativeSession !== undefined &&
|
|
24
|
+
!isPlainTextInspectionArgs(args) &&
|
|
25
|
+
extractExplicitSessionName(args) === undefined) {
|
|
26
|
+
return ["--session", nativeSession, ...args];
|
|
398
27
|
}
|
|
399
|
-
return
|
|
400
|
-
}
|
|
401
|
-
export function getImplicitSessionIdleTimeoutMs(env = getAgentBrowserProcessEnvironment()) {
|
|
402
|
-
return parseTimeoutMs(env[IMPLICIT_SESSION_IDLE_TIMEOUT_ENV], 0) ??
|
|
403
|
-
parseTimeoutMs(env[AGENT_BROWSER_IDLE_TIMEOUT_ENV], 0) ??
|
|
404
|
-
DEFAULT_IMPLICIT_SESSION_IDLE_TIMEOUT_MS;
|
|
28
|
+
return args;
|
|
405
29
|
}
|
|
406
|
-
function
|
|
407
|
-
return
|
|
30
|
+
function jsonPrefix(args) {
|
|
31
|
+
return getBooleanFlagValue(args, "--json") === undefined ? ["--json"] : [];
|
|
408
32
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if (!succeeded) {
|
|
426
|
-
return { active: priorActive, ...(priorNamespace ? { namespace: priorNamespace } : {}), sessionName: priorSessionName };
|
|
427
|
-
}
|
|
428
|
-
return {
|
|
429
|
-
active: true,
|
|
430
|
-
...(managedSessionNamespace ? { namespace: managedSessionNamespace } : {}),
|
|
431
|
-
replacedSessionName: priorActive && priorSessionName !== managedSessionName ? priorSessionName : undefined,
|
|
432
|
-
sessionName: managedSessionName,
|
|
33
|
+
function planningFailure(args) {
|
|
34
|
+
const invalidValueFlag = getInvalidValueFlagDetails(args);
|
|
35
|
+
const repeatedFlag = ["--session", "--namespace"].find((flag) => scanUpstreamGlobalFlagOccurrences(args, flag).length > 1);
|
|
36
|
+
if (!invalidValueFlag && repeatedFlag === undefined) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const validationError = invalidValueFlag
|
|
40
|
+
? formatInvalidValueFlagError(invalidValueFlag)
|
|
41
|
+
: `Multiple ${repeatedFlag ?? ""} flags are not supported. Pass a single ${repeatedFlag ?? ""} value; upstream uses the last occurrence while this wrapper would otherwise mis-attribute managed-session ownership.`;
|
|
42
|
+
const plan = {
|
|
43
|
+
commandInfo: {},
|
|
44
|
+
effectiveArgs: jsonPrefix(args),
|
|
45
|
+
plainTextInspection: false,
|
|
46
|
+
startupScopedFlags: [],
|
|
47
|
+
usedImplicitSession: false,
|
|
48
|
+
validationError,
|
|
433
49
|
};
|
|
50
|
+
return invalidValueFlag ? { ...plan, invalidValueFlag } : plan;
|
|
434
51
|
}
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
const
|
|
459
|
-
const
|
|
460
|
-
const results = Array.isArray(cleanup?.results) ? cleanup.results : [];
|
|
461
|
-
const closedSessions = [];
|
|
462
|
-
for (const result of results) {
|
|
463
|
-
if (!isRecord(result) || !Array.isArray(result.steps))
|
|
464
|
-
continue;
|
|
465
|
-
const record = isRecord(result.record) ? result.record : undefined;
|
|
466
|
-
const fallbackNamespace = typeof record?.namespace === "string"
|
|
467
|
-
? record.namespace
|
|
468
|
-
: typeof details.namespace === "string" ? details.namespace : undefined;
|
|
469
|
-
for (const step of result.steps) {
|
|
470
|
-
if (!isRecord(step) || step.resource !== "managed-session")
|
|
471
|
-
continue;
|
|
472
|
-
if (step.state !== "removed" && step.state !== "already-gone")
|
|
473
|
-
continue;
|
|
474
|
-
const sessionName = getRestorableManagedSessionName(step.sessionName, fallbackSessionName)
|
|
475
|
-
?? getRestorableManagedSessionName(record?.sessionName, fallbackSessionName);
|
|
476
|
-
const namespace = typeof step.namespace === "string" ? step.namespace : fallbackNamespace;
|
|
477
|
-
if (sessionName)
|
|
478
|
-
closedSessions.push({ namespace, sessionName });
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
return closedSessions;
|
|
482
|
-
}
|
|
483
|
-
export function restoreManagedSessionStateFromBranch(branch, fallbackSessionName) {
|
|
484
|
-
const restoreDisabledIdentities = new Map();
|
|
485
|
-
let restoredState = {
|
|
486
|
-
active: false,
|
|
487
|
-
sessionName: fallbackSessionName,
|
|
488
|
-
};
|
|
489
|
-
let activeRestoreRank = 0;
|
|
490
|
-
let closedSessionName;
|
|
491
|
-
let freshSessionOrdinal = 0;
|
|
492
|
-
const freshSessionRanks = new Map();
|
|
493
|
-
const applyManagedClose = (sessionName, namespace) => {
|
|
494
|
-
namespace = canonicalizeAgentBrowserNamespace(namespace);
|
|
495
|
-
const restoreRank = getManagedSessionRestoreRank({
|
|
496
|
-
fallbackSessionName,
|
|
497
|
-
freshSessionRanks,
|
|
498
|
-
sessionName,
|
|
499
|
-
});
|
|
500
|
-
if (restoreRank === undefined || sessionName !== restoredState.sessionName || namespace !== restoredState.namespace)
|
|
501
|
-
return;
|
|
502
|
-
restoredState = { active: false, sessionName: restoredState.sessionName };
|
|
503
|
-
closedSessionName = sessionName;
|
|
504
|
-
};
|
|
505
|
-
for (const entry of branch) {
|
|
506
|
-
const message = getBrowserResultMessage(entry);
|
|
507
|
-
if (!message) {
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
|
-
const details = isRecord(message.details) ? message.details : undefined;
|
|
511
|
-
if (!details) {
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
const args = isStringArray(details.args) ? details.args : [];
|
|
515
|
-
if (isPlainTextInspectionArgs(args)) {
|
|
516
|
-
continue;
|
|
517
|
-
}
|
|
518
|
-
for (const cleanupSession of getElectronCleanupClosedManagedSessions(details, fallbackSessionName)) {
|
|
519
|
-
applyManagedClose(cleanupSession.sessionName, cleanupSession.namespace);
|
|
520
|
-
}
|
|
521
|
-
const explicitSessionName = extractExplicitSessionName(args);
|
|
522
|
-
const sessionName = typeof details.sessionName === "string" ? details.sessionName : undefined;
|
|
523
|
-
const namespace = canonicalizeAgentBrowserNamespace(typeof details.namespace === "string" ? details.namespace : undefined);
|
|
524
|
-
const sessionMode = details.sessionMode === "fresh" || details.sessionMode === "auto" ? details.sessionMode : undefined;
|
|
525
|
-
const usedImplicitSession = details.usedImplicitSession === true;
|
|
526
|
-
const commandTokens = extractUpstreamCommandTokens(args);
|
|
527
|
-
const command = typeof details.command === "string" ? details.command : parseCommandInfo(args).command;
|
|
528
|
-
const batchCloseLifecycle = getSuccessfulBatchCloseLifecycle(details.batchSteps);
|
|
529
|
-
const nestedBatchEndsClosed = batchCloseLifecycle?.endsClosed === true;
|
|
530
|
-
const nestedBatchRemainsActive = batchCloseLifecycle?.endsClosed === false;
|
|
531
|
-
const closeAllApplied = details.closeAllApplied === true
|
|
532
|
-
|| (message.isError !== true && isCloseAllCommand(commandTokens))
|
|
533
|
-
|| batchHasSuccessfulCloseAll(details.batchSteps);
|
|
534
|
-
const commandClosesSession = isCloseCommand(command) || nestedBatchEndsClosed;
|
|
535
|
-
const outcome = typeof details.managedSessionOutcome === "object" && details.managedSessionOutcome !== null ? details.managedSessionOutcome : undefined;
|
|
536
|
-
const outcomeStatus = typeof outcome?.status === "string" ? outcome.status : undefined;
|
|
537
|
-
const outcomeCurrentSessionName = typeof outcome?.currentSessionName === "string" ? outcome.currentSessionName : undefined;
|
|
538
|
-
const outcomeAttemptedSessionName = getRestorableManagedSessionName(outcome?.attemptedSessionName, fallbackSessionName);
|
|
539
|
-
const outcomeClosedSessionName = outcomeStatus === "closed" && outcome?.succeeded === true
|
|
540
|
-
? outcomeAttemptedSessionName ?? getRestorableManagedSessionName(outcomeCurrentSessionName, fallbackSessionName) ?? getRestorableManagedSessionName(sessionName, fallbackSessionName)
|
|
541
|
-
: undefined;
|
|
542
|
-
const restorableDetailSessionName = getRestorableManagedSessionName(sessionName, fallbackSessionName);
|
|
543
|
-
if (closeAllApplied && restoredState.active) {
|
|
544
|
-
const restoredKey = getAgentBrowserSessionIdentityKey(restoredState.sessionName, restoredState.namespace);
|
|
545
|
-
const resultKey = restorableDetailSessionName ? getAgentBrowserSessionIdentityKey(restorableDetailSessionName, namespace) : undefined;
|
|
546
|
-
const retainsCurrentSession = nestedBatchRemainsActive && resultKey === restoredKey;
|
|
547
|
-
if (isAgentBrowserSessionIdentityKeyInNamespace(restoredKey, namespace) && !retainsCurrentSession) {
|
|
548
|
-
applyManagedClose(restoredState.sessionName, restoredState.namespace);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
const explicitCloseSessionName = commandClosesSession && explicitSessionName && restorableDetailSessionName === explicitSessionName
|
|
552
|
-
? restorableDetailSessionName
|
|
553
|
-
: undefined;
|
|
554
|
-
// Sticky restore policy is session-identity state and must apply even for explicit
|
|
555
|
-
// `--session <current-managed>` rows that are not used for managed-session lifecycle replay.
|
|
556
|
-
if (details.managedSessionRestoreDisabled === true && typeof sessionName === "string") {
|
|
557
|
-
restoreDisabledIdentities.set(getAgentBrowserSessionIdentityKey(sessionName, namespace), { namespace, sessionName });
|
|
558
|
-
}
|
|
559
|
-
const managedSessionName = outcomeClosedSessionName ?? (!explicitSessionName &&
|
|
560
|
-
restorableDetailSessionName &&
|
|
561
|
-
(usedImplicitSession || sessionMode === "fresh")
|
|
562
|
-
? restorableDetailSessionName
|
|
563
|
-
: commandClosesSession
|
|
564
|
-
? explicitCloseSessionName
|
|
565
|
-
: undefined);
|
|
566
|
-
if (!managedSessionName) {
|
|
567
|
-
continue;
|
|
568
|
-
}
|
|
569
|
-
const restoreRank = getManagedSessionRestoreRank({
|
|
570
|
-
fallbackSessionName,
|
|
571
|
-
freshSessionRanks,
|
|
572
|
-
sessionName: managedSessionName,
|
|
573
|
-
});
|
|
574
|
-
if (restoreRank === undefined) {
|
|
575
|
-
continue;
|
|
576
|
-
}
|
|
577
|
-
freshSessionOrdinal = Math.max(freshSessionOrdinal, restoreRank);
|
|
578
|
-
const messageIsError = typeof message.isError === "boolean" ? message.isError : undefined;
|
|
579
|
-
const exitCode = typeof details.exitCode === "number" ? details.exitCode : undefined;
|
|
580
|
-
const outcomeActiveAfter = outcome?.activeAfter === true;
|
|
581
|
-
const outcomeRepresentsActiveCurrentSession = outcomeActiveAfter && outcomeCurrentSessionName === managedSessionName && (outcomeStatus === "created" || outcomeStatus === "replaced" || outcomeStatus === "unchanged");
|
|
582
|
-
const succeeded = outcomeRepresentsActiveCurrentSession || nestedBatchRemainsActive
|
|
583
|
-
? true
|
|
584
|
-
: messageIsError === undefined ? exitCode === undefined || exitCode === 0 : !messageIsError;
|
|
585
|
-
if (commandClosesSession || outcomeClosedSessionName) {
|
|
586
|
-
if (nestedBatchEndsClosed || outcomeClosedSessionName || succeeded) {
|
|
587
|
-
restoreDisabledIdentities.delete(getAgentBrowserSessionIdentityKey(managedSessionName, namespace));
|
|
588
|
-
applyManagedClose(managedSessionName, namespace);
|
|
589
|
-
}
|
|
590
|
-
continue;
|
|
591
|
-
}
|
|
592
|
-
const staleCompletion = succeeded && restoreRank < activeRestoreRank;
|
|
593
|
-
if (staleCompletion) {
|
|
594
|
-
continue;
|
|
595
|
-
}
|
|
596
|
-
restoredState = resolveManagedSessionState({
|
|
597
|
-
command,
|
|
598
|
-
managedSessionName,
|
|
599
|
-
managedSessionNamespace: namespace,
|
|
600
|
-
priorActive: restoredState.active,
|
|
601
|
-
priorNamespace: restoredState.namespace,
|
|
602
|
-
priorSessionName: restoredState.sessionName,
|
|
603
|
-
succeeded,
|
|
604
|
-
});
|
|
605
|
-
if (succeeded && restoredState.active) {
|
|
606
|
-
activeRestoreRank = restoreRank;
|
|
607
|
-
closedSessionName = undefined;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
52
|
+
function effectiveStartupFlags(args, managedNamespace) {
|
|
53
|
+
const explicitNamespacePresent = scanUpstreamGlobalFlagOccurrences(args, "--namespace").length > 0;
|
|
54
|
+
const explicitNamespace = extractExplicitNamespace(args);
|
|
55
|
+
return getStartupScopedFlags(args).filter((flag) => !(flag === "--namespace" &&
|
|
56
|
+
explicitNamespacePresent &&
|
|
57
|
+
explicitNamespace === canonicalizeAgentBrowserNamespace(managedNamespace)));
|
|
58
|
+
}
|
|
59
|
+
function targetsActiveManagedSession(selection, options, needsSession) {
|
|
60
|
+
const { sessionName } = selection;
|
|
61
|
+
return (options.managedSessionActive &&
|
|
62
|
+
needsSession &&
|
|
63
|
+
sessionName !== undefined &&
|
|
64
|
+
sessionName.length > 0 &&
|
|
65
|
+
getAgentBrowserSessionIdentityKey(sessionName, selection.namespace) ===
|
|
66
|
+
getAgentBrowserSessionIdentityKey(options.managedSessionName, options.managedSessionNamespace));
|
|
67
|
+
}
|
|
68
|
+
function activeLaunchRecovery(args, flags, command, prior) {
|
|
69
|
+
if (flags.length === 0 ||
|
|
70
|
+
isCloseCommand(command) ||
|
|
71
|
+
(prior.validationError !== undefined && prior.validationError.length > 0)) {
|
|
72
|
+
return prior;
|
|
73
|
+
}
|
|
74
|
+
const explicitSession = extractExplicitSessionName(args);
|
|
75
|
+
const explicit = explicitSession !== undefined && explicitSession.length > 0;
|
|
76
|
+
const recoveryArgs = explicit ? stripExplicitIdentityArgs(args, "--session") : args;
|
|
610
77
|
return {
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
78
|
+
recoveryHint: freshSessionRecoveryHint(recoveryArgs, launchFlagsRecoveryReason()),
|
|
79
|
+
validationError: [
|
|
80
|
+
`The current extension-managed agent-browser session is already running, so launch-scoped flags ${flags.join(", ")} would replace or be ignored by upstream agent-browser.`,
|
|
81
|
+
explicit
|
|
82
|
+
? 'Remove the explicit `--session` and retry with `sessionMode: "fresh"` to force a fresh upstream launch.'
|
|
83
|
+
: 'Retry this call with `sessionMode: "fresh"` to force a fresh upstream launch.',
|
|
84
|
+
].join(" "),
|
|
615
85
|
};
|
|
616
86
|
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
}
|
|
620
|
-
function createCwdHash(cwd) {
|
|
621
|
-
return createHash("sha256").update(`cwd:${cwd}`).digest("hex").slice(0, SESSION_NAME_CWD_HASH_LENGTH);
|
|
622
|
-
}
|
|
623
|
-
export function createImplicitSessionName(sessionId, cwd, ephemeralSeed, platform = process.platform) {
|
|
624
|
-
const normalizedSessionId = sessionId?.replaceAll("-", "").toLowerCase();
|
|
625
|
-
if (platform === "android") {
|
|
626
|
-
const identity = normalizedSessionId ? `session:${normalizedSessionId}:cwd:${cwd}` : `ephemeral:${cwd}:${ephemeralSeed}`;
|
|
627
|
-
const digest = createHash("sha256").update(identity).digest("hex").slice(0, ANDROID_SESSION_NAME_IDENTITY_LENGTH);
|
|
628
|
-
return `${MANAGED_SESSION_NAME_PREFIX}${digest}`;
|
|
629
|
-
}
|
|
630
|
-
const slug = basename(cwd)
|
|
631
|
-
.toLowerCase()
|
|
632
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
633
|
-
.replace(/^-+|-+$/g, "")
|
|
634
|
-
.slice(0, MAX_PROJECT_SLUG_LENGTH) || "project";
|
|
635
|
-
const cwdHash = createCwdHash(cwd);
|
|
636
|
-
if (normalizedSessionId) {
|
|
637
|
-
const stableSessionId = createHash("sha256")
|
|
638
|
-
.update(`session:${normalizedSessionId}`)
|
|
639
|
-
.digest("hex")
|
|
640
|
-
.slice(0, SESSION_NAME_SESSION_ID_LENGTH);
|
|
641
|
-
return `${MANAGED_SESSION_NAME_PREFIX}${slug}-${stableSessionId}-${cwdHash}`;
|
|
642
|
-
}
|
|
643
|
-
const digest = createHash("sha256")
|
|
644
|
-
.update(`ephemeral:${cwd}:${ephemeralSeed}`)
|
|
645
|
-
.digest("hex")
|
|
646
|
-
.slice(0, SESSION_NAME_SESSION_ID_LENGTH);
|
|
647
|
-
return `${MANAGED_SESSION_NAME_PREFIX}${slug}-${digest}-${cwdHash}`;
|
|
648
|
-
}
|
|
649
|
-
export function createFreshSessionName(baseSessionName, ephemeralSeed, ordinal) {
|
|
650
|
-
const suffix = createHash("sha256")
|
|
651
|
-
.update(`fresh:${baseSessionName}:${ephemeralSeed}:${ordinal}`)
|
|
652
|
-
.digest("hex")
|
|
653
|
-
.slice(0, 10);
|
|
654
|
-
return `${baseSessionName}-fresh-${suffix}`;
|
|
655
|
-
}
|
|
656
|
-
function getSingleKeyCommandValidationError(args) {
|
|
657
|
-
const { commandInfo, upstreamCommandTokens: commandTokens } = parseArgvDescriptor(args);
|
|
658
|
-
const command = commandInfo.command;
|
|
659
|
-
if (command !== "press" && command !== "key" && command !== "keydown" && command !== "keyup")
|
|
660
|
-
return undefined;
|
|
661
|
-
if (commandTokens.length === 2)
|
|
662
|
-
return undefined;
|
|
663
|
-
const label = command === "key" ? "key/press" : command;
|
|
664
|
-
return `agent-browser ${label} accepts exactly one key argument. Do not pass a selector or ref to ${label}; focus or click the target first, then run ${command} <key> (for example: focus @e1, then press Enter).`;
|
|
665
|
-
}
|
|
666
|
-
function getBareMcpValidationError(args) {
|
|
667
|
-
const { commandInfo, upstreamCommandTokens: commandTokens } = parseArgvDescriptor(args);
|
|
668
|
-
if (commandInfo.command !== "mcp")
|
|
669
|
-
return undefined;
|
|
670
|
-
if (commandTokens.includes("--help") || commandTokens.includes("-h"))
|
|
671
|
-
return undefined;
|
|
672
|
-
return "agent-browser mcp starts a stdio MCP server for external MCP clients, not a one-shot native agent_browser tool workflow. Use the native agent_browser tool modes directly, or configure an MCP client to launch `agent-browser mcp`. Use `mcp --help` for help.";
|
|
673
|
-
}
|
|
674
|
-
function getUnsupportedInlineWaitDownloadError(args) {
|
|
675
|
-
const descriptor = parseArgvDescriptor(args);
|
|
676
|
-
if (descriptor.commandInfo.command !== "wait" || !descriptor.upstreamCommandTokens.some((token) => token.startsWith("--download=")))
|
|
677
|
-
return undefined;
|
|
678
|
-
return `agent-browser ${TARGET_AGENT_BROWSER_VERSION} does not support \`wait --download=<path>\`. Pass the optional path as a separate argument: \`wait --download <path>\` (or \`wait -d <path>\`).`;
|
|
679
|
-
}
|
|
680
|
-
function getBareNoSandboxValidationError(args, batchStep) {
|
|
681
|
-
// Native batch rows skip global parsing; --args is effective only on the outer CLI call.
|
|
682
|
-
const tokens = batchStep ? args : stripUpstreamGlobalFlags(args);
|
|
683
|
-
const command = tokens[0];
|
|
684
|
-
const leading = command === "--no-sandbox";
|
|
685
|
-
if (!leading && (!isOpenNavigationCommand(command) || !tokens.slice(1).includes("--no-sandbox")))
|
|
686
|
-
return undefined;
|
|
687
|
-
const explanation = leading
|
|
688
|
-
? "`--no-sandbox` is not an agent-browser command."
|
|
689
|
-
: `\`--no-sandbox\` is ignored as an option by \`${command}\`.`;
|
|
690
|
-
return `${explanation} It is a Chromium launch argument. Put it in top-level \`--args\` and start a fresh session: { args: ["--args", "--no-sandbox", "open", "https://example.com"], sessionMode: "fresh" }. For batch, put --args before batch, not inside a step.`;
|
|
691
|
-
}
|
|
692
|
-
export function validateToolArgs(args, options = {}) {
|
|
693
|
-
if (args.length === 0) {
|
|
694
|
-
return "`args` must contain at least one agent-browser command token.";
|
|
695
|
-
}
|
|
696
|
-
const shellOperator = args.find((token) => SHELL_OPERATOR_TOKENS.has(token));
|
|
697
|
-
if (shellOperator) {
|
|
698
|
-
return `Do not pass shell operators like \`${shellOperator}\`. Pass exact agent-browser CLI arguments only.`;
|
|
699
|
-
}
|
|
700
|
-
const sessionModeArg = args.find((token) => token === "--session-mode" || token.startsWith("--session-mode="));
|
|
701
|
-
if (sessionModeArg) {
|
|
702
|
-
return "Do not pass `--session-mode` in args. Use the top-level agent_browser `sessionMode` field instead, for example { args: [\"--profile\", \"Default\", \"open\", \"https://example.com\"], sessionMode: \"fresh\" }.";
|
|
703
|
-
}
|
|
704
|
-
const inspection = !options.batchStep && isPlainTextInspectionArgs(args);
|
|
705
|
-
const invalidValueFlag = inspection ? undefined : getInvalidValueFlagDetails(args, !options.batchStep);
|
|
706
|
-
if (invalidValueFlag?.reason === "unsupported-assignment")
|
|
707
|
-
return formatInvalidValueFlagError(invalidValueFlag, options.batchStep);
|
|
708
|
-
return (inspection ? undefined : getBareNoSandboxValidationError(args, options.batchStep === true))
|
|
709
|
-
?? getBareMcpValidationError(args) ?? getSingleKeyCommandValidationError(args) ?? getUnsupportedInlineWaitDownloadError(args);
|
|
710
|
-
}
|
|
711
|
-
function getInvalidValueFlagDetails(args, allowRestoreAssignment = true) {
|
|
712
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
713
|
-
const token = args[index];
|
|
714
|
-
if (!token.startsWith("-")) {
|
|
715
|
-
continue;
|
|
716
|
-
}
|
|
717
|
-
const normalizedToken = token.split("=", 1)[0] ?? token;
|
|
718
|
-
if (token.includes("=")
|
|
719
|
-
&& (PREVALIDATED_VALUE_FLAGS.has(normalizedToken)
|
|
720
|
-
|| GLOBAL_BOOLEAN_FLAGS_WITH_OPTIONAL_VALUES.has(normalizedToken)
|
|
721
|
-
|| (!allowRestoreAssignment && normalizedToken === "--restore"))) {
|
|
722
|
-
return {
|
|
723
|
-
flag: normalizedToken,
|
|
724
|
-
index,
|
|
725
|
-
reason: "unsupported-assignment",
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
if (!PREVALIDATED_VALUE_FLAGS.has(normalizedToken)) {
|
|
729
|
-
continue;
|
|
730
|
-
}
|
|
731
|
-
const receivedToken = args[index + 1];
|
|
732
|
-
if (receivedToken === undefined || (normalizedToken === "--args" && receivedToken.length === 0)) {
|
|
733
|
-
return {
|
|
734
|
-
flag: normalizedToken,
|
|
735
|
-
index,
|
|
736
|
-
reason: "missing-value",
|
|
737
|
-
};
|
|
738
|
-
}
|
|
739
|
-
if (receivedToken.startsWith("-") && !GLOBAL_VALUE_FLAGS_ALLOWING_DASH_VALUE.has(normalizedToken)) {
|
|
740
|
-
return {
|
|
741
|
-
flag: normalizedToken,
|
|
742
|
-
index,
|
|
743
|
-
reason: "unexpected-flag",
|
|
744
|
-
receivedToken,
|
|
745
|
-
};
|
|
746
|
-
}
|
|
747
|
-
index += 1;
|
|
748
|
-
}
|
|
749
|
-
return undefined;
|
|
750
|
-
}
|
|
751
|
-
function formatInvalidValueFlagError(details, batchStep = false) {
|
|
752
|
-
if (details.reason === "unsupported-assignment") {
|
|
753
|
-
if (batchStep) {
|
|
754
|
-
return details.flag === "--restore"
|
|
755
|
-
? "Global `--restore=<key>` belongs before `batch` in top-level args, not inside a batch step."
|
|
756
|
-
: `Global \`${details.flag}=<value>\` is not supported inside a batch step. Move \`${details.flag}\` and its value before \`batch\` as separate top-level args.`;
|
|
757
|
-
}
|
|
758
|
-
return `agent-browser ${TARGET_AGENT_BROWSER_VERSION} does not support \`${details.flag}=<value>\`. Pass \`${details.flag}\` and its value as separate arguments.`;
|
|
759
|
-
}
|
|
760
|
-
if (details.reason === "unexpected-flag" && details.receivedToken) {
|
|
761
|
-
return `Flag \`${details.flag}\` requires a value, but received \`${details.receivedToken}\` instead. Pass a non-flag value immediately after \`${details.flag}\`.`;
|
|
762
|
-
}
|
|
763
|
-
return `Flag \`${details.flag}\` requires a value immediately after it. Pass a non-flag token like \`${details.flag} demo\`.`;
|
|
764
|
-
}
|
|
765
|
-
function hasFlagToken(args, flag) {
|
|
766
|
-
return args.some((token) => token === flag || token.startsWith(`${flag}=`));
|
|
767
|
-
}
|
|
768
|
-
function normalizeComparableUrl(url) {
|
|
769
|
-
const normalizedUrl = url.trim();
|
|
770
|
-
if (normalizedUrl.length === 0) {
|
|
771
|
-
return undefined;
|
|
87
|
+
function activeCompatibilityPlan(args, requested, existing, prior) {
|
|
88
|
+
if (!canUseHeadlessCompatibilityUserAgent(args)) {
|
|
89
|
+
return { ...prior, compatibilityWorkaround: requested };
|
|
772
90
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
return undefined;
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
function normalizeTabSelectionValue(value) {
|
|
783
|
-
const normalizedValue = value?.trim();
|
|
784
|
-
return normalizedValue && normalizedValue.length > 0 ? normalizedValue : undefined;
|
|
785
|
-
}
|
|
786
|
-
function extractTabSelection(tab) {
|
|
787
|
-
const tabId = normalizeTabSelectionValue(tab.tabId);
|
|
788
|
-
if (tabId) {
|
|
789
|
-
return { selectedTab: tabId, selectionKind: "tabId" };
|
|
790
|
-
}
|
|
791
|
-
const label = normalizeTabSelectionValue(tab.label);
|
|
792
|
-
if (label) {
|
|
793
|
-
return { selectedTab: label, selectionKind: "label" };
|
|
794
|
-
}
|
|
795
|
-
if (typeof tab.index === "number" && Number.isInteger(tab.index) && tab.index >= 0) {
|
|
796
|
-
return { selectedTab: String(tab.index), selectionKind: "index" };
|
|
797
|
-
}
|
|
798
|
-
return undefined;
|
|
799
|
-
}
|
|
800
|
-
function parseComparableNavigationUrl(url) {
|
|
801
|
-
try {
|
|
802
|
-
return new URL(url);
|
|
803
|
-
}
|
|
804
|
-
catch {
|
|
805
|
-
try {
|
|
806
|
-
return new URL(`https://${url}`);
|
|
807
|
-
}
|
|
808
|
-
catch {
|
|
809
|
-
return undefined;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
export function getDefaultHeadlessCompatUserAgent(platform = process.platform) {
|
|
814
|
-
return DEFAULT_HEADLESS_COMPAT_USER_AGENT_BY_PLATFORM[platform] ?? FALLBACK_HEADLESS_COMPAT_USER_AGENT;
|
|
815
|
-
}
|
|
816
|
-
export function canUseHeadlessCompatibilityUserAgent(args, env = getAgentBrowserProcessEnvironment()) {
|
|
817
|
-
if (env.AGENT_BROWSER_SESSION !== undefined)
|
|
818
|
-
return false;
|
|
819
|
-
if (hasFlagToken(args, "--user-agent") || hasFlagToken(args, "--args"))
|
|
820
|
-
return false;
|
|
821
|
-
if (hasFlagToken(args, "--cdp") || hasFlagToken(args, "--provider") || hasFlagToken(args, "-p"))
|
|
822
|
-
return false;
|
|
823
|
-
if (env.AGENT_BROWSER_USER_AGENT !== undefined || env.AGENT_BROWSER_ARGS !== undefined || env.AGENT_BROWSER_CDP !== undefined || env.AGENT_BROWSER_PROVIDER !== undefined)
|
|
824
|
-
return false;
|
|
825
|
-
if ((getBooleanFlagValue(args, "--headed") ?? isUpstreamEnvFlagEnabled(env.AGENT_BROWSER_HEADED))
|
|
826
|
-
|| (getBooleanFlagValue(args, "--auto-connect") ?? isUpstreamEnvFlagEnabled(env.AGENT_BROWSER_AUTO_CONNECT)))
|
|
827
|
-
return false;
|
|
828
|
-
const engine = scanUpstreamGlobalFlagOccurrences(args, "--engine").at(-1)?.value ?? env.AGENT_BROWSER_ENGINE;
|
|
829
|
-
return !engine || engine === "chrome";
|
|
830
|
-
}
|
|
831
|
-
function getCompatibilityWorkaround(args, commandInfo) {
|
|
832
|
-
if (!commandInfo.command || !isOpenNavigationCommand(commandInfo.command) || !commandInfo.subcommand || !canUseHeadlessCompatibilityUserAgent(args))
|
|
833
|
-
return undefined;
|
|
834
|
-
const parsedTargetUrl = parseComparableNavigationUrl(commandInfo.subcommand);
|
|
835
|
-
if (!parsedTargetUrl || !["http:", "https:"].includes(parsedTargetUrl.protocol))
|
|
836
|
-
return undefined;
|
|
837
|
-
const hostname = parsedTargetUrl.hostname.toLowerCase();
|
|
838
|
-
if (hostname === CLOUDFLARE_HEADLESS_COMPAT_HOST) {
|
|
91
|
+
if (requested &&
|
|
92
|
+
!existing &&
|
|
93
|
+
(prior.validationError === undefined || prior.validationError.length === 0)) {
|
|
94
|
+
const sessionName = extractExplicitSessionName(args);
|
|
95
|
+
const explicit = sessionName !== undefined && sessionName.length > 0;
|
|
96
|
+
const recoveryArgs = explicit ? stripExplicitIdentityArgs(args, "--session") : args;
|
|
839
97
|
return {
|
|
840
|
-
|
|
841
|
-
|
|
98
|
+
compatibilityWorkaround: undefined,
|
|
99
|
+
recoveryHint: freshSessionRecoveryHint(recoveryArgs, "The requested site compatibility user agent is launch-scoped and needs a fresh browser session."),
|
|
100
|
+
validationError: explicit
|
|
101
|
+
? 'The current extension-managed agent-browser session is already running without the user agent required by this site. Remove the explicit `--session` and retry with `sessionMode: "fresh"` so the compatibility user agent is applied at launch.'
|
|
102
|
+
: 'The current extension-managed agent-browser session is already running without the user agent required by this site. Retry this call with `sessionMode: "fresh"` so the compatibility user agent is applied at launch.',
|
|
842
103
|
};
|
|
843
104
|
}
|
|
844
|
-
|
|
845
|
-
|
|
105
|
+
return { ...prior, compatibilityWorkaround: requested ?? existing };
|
|
106
|
+
}
|
|
107
|
+
function inspectionPlan(args, commandInfo, startupScopedFlags) {
|
|
108
|
+
const explicitNamespacePresent = scanUpstreamGlobalFlagOccurrences(args, "--namespace").length > 0;
|
|
846
109
|
return {
|
|
847
|
-
|
|
848
|
-
|
|
110
|
+
commandInfo,
|
|
111
|
+
effectiveArgs: [...args],
|
|
112
|
+
namespace: explicitNamespacePresent ? (extractExplicitNamespace(args) ?? "") : undefined,
|
|
113
|
+
plainTextInspection: true,
|
|
114
|
+
startupScopedFlags,
|
|
115
|
+
usedImplicitSession: false,
|
|
849
116
|
};
|
|
850
117
|
}
|
|
851
|
-
function
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
const startupScopedFlags = getStartupScopedFlags(args).filter((flag) => !(flag === "--namespace" && explicitNamespacePresent && explicitNamespace === managedSessionNamespace));
|
|
881
|
-
const plainTextInspection = isPlainTextInspectionArgs(args);
|
|
882
|
-
const argvDescriptor = parseArgvDescriptor(args);
|
|
883
|
-
const commandInfo = argvDescriptor.commandInfo;
|
|
884
|
-
const commandNeedsManagedSession = !plainTextInspection && !options.browserIndependentReadConfirmation && needsManagedSession(argvDescriptor, options.stdin);
|
|
885
|
-
const effectiveArgs = plainTextInspection ? [...args] : getBooleanFlagValue(args, "--json") !== undefined ? [] : ["--json"];
|
|
886
|
-
let namespace = explicitNamespacePresent ? explicitNamespace ?? "" : undefined;
|
|
887
|
-
if (plainTextInspection) {
|
|
888
|
-
return {
|
|
889
|
-
commandInfo,
|
|
890
|
-
effectiveArgs,
|
|
891
|
-
namespace,
|
|
892
|
-
plainTextInspection,
|
|
893
|
-
startupScopedFlags,
|
|
894
|
-
usedImplicitSession: false,
|
|
895
|
-
};
|
|
896
|
-
}
|
|
897
|
-
if (invalidValueFlag) {
|
|
898
|
-
return {
|
|
899
|
-
commandInfo: {},
|
|
900
|
-
effectiveArgs,
|
|
901
|
-
invalidValueFlag,
|
|
902
|
-
plainTextInspection: false,
|
|
903
|
-
startupScopedFlags: [],
|
|
904
|
-
usedImplicitSession: false,
|
|
905
|
-
validationError: formatInvalidValueFlagError(invalidValueFlag),
|
|
906
|
-
};
|
|
907
|
-
}
|
|
908
|
-
for (const flag of ["--session", "--namespace"]) {
|
|
909
|
-
if (countExplicitGlobalFlags(args, flag) <= 1)
|
|
910
|
-
continue;
|
|
911
|
-
return {
|
|
912
|
-
commandInfo: {},
|
|
913
|
-
effectiveArgs,
|
|
914
|
-
plainTextInspection: false,
|
|
915
|
-
startupScopedFlags: [],
|
|
916
|
-
usedImplicitSession: false,
|
|
917
|
-
validationError: `Multiple ${flag} flags are not supported. Pass a single ${flag} value; upstream uses the last occurrence while this wrapper would otherwise mis-attribute managed-session ownership.`,
|
|
918
|
-
};
|
|
919
|
-
}
|
|
920
|
-
const explicitSessionName = extractExplicitSessionName(args);
|
|
921
|
-
if (explicitSessionName && !explicitNamespacePresent) {
|
|
922
|
-
const targetsCurrentManagedSession = options.managedSessionActive
|
|
923
|
-
&& getAgentBrowserSessionIdentityKey(explicitSessionName, managedSessionNamespace)
|
|
924
|
-
=== getAgentBrowserSessionIdentityKey(options.managedSessionName, managedSessionNamespace);
|
|
925
|
-
namespace = targetsCurrentManagedSession
|
|
926
|
-
? managedSessionNamespace
|
|
927
|
-
: resolveAgentBrowserNamespace(args, getAgentBrowserProcessEnvironment().AGENT_BROWSER_NAMESPACE);
|
|
928
|
-
}
|
|
929
|
-
const shouldCreateFreshManagedSession = !explicitSessionName && options.sessionMode === "fresh" && commandInfo.command !== undefined && !isCloseCommand(commandInfo.command);
|
|
930
|
-
let argsToAppend = args;
|
|
931
|
-
const requestedCompatibilityWorkaround = getCompatibilityWorkaround(args, commandInfo);
|
|
932
|
-
let compatibilityWorkaround = requestedCompatibilityWorkaround;
|
|
933
|
-
if (explicitSessionName && explicitNamespacePresent) {
|
|
934
|
-
effectiveArgs.push("--namespace", explicitNamespace ?? "");
|
|
935
|
-
argsToAppend = stripExplicitNamespaceArgs(args);
|
|
936
|
-
}
|
|
937
|
-
let managedSessionName;
|
|
938
|
-
let recoveryHint;
|
|
939
|
-
let sessionName = explicitSessionName;
|
|
940
|
-
let usedImplicitSession = false;
|
|
941
|
-
let validationError;
|
|
942
|
-
if (!explicitSessionName && options.sessionMode === "auto" && commandNeedsManagedSession) {
|
|
943
|
-
if (options.managedSessionActive && startupScopedFlags.length > 0) {
|
|
944
|
-
recoveryHint = {
|
|
945
|
-
exampleArgs: args,
|
|
946
|
-
exampleParams: { args, sessionMode: "fresh" },
|
|
947
|
-
reason: `Launch-scoped flags (${LAUNCH_SCOPED_FLAG_LABEL}) need a fresh upstream launch once the extension-managed session is already active.`,
|
|
948
|
-
recommendedSessionMode: "fresh",
|
|
949
|
-
};
|
|
950
|
-
validationError = [
|
|
951
|
-
`The current extension-managed agent-browser session is already running, so launch-scoped flags ${startupScopedFlags.join(", ")} would be ignored by upstream agent-browser.`,
|
|
952
|
-
"Retry this call with `sessionMode: \"fresh\"` to force a fresh upstream launch, or pass an explicit `--session ...` if you want to name the new session yourself.",
|
|
953
|
-
].join(" ");
|
|
954
|
-
}
|
|
955
|
-
else {
|
|
956
|
-
namespace = explicitNamespacePresent ? explicitNamespace ?? "" : managedSessionNamespace;
|
|
957
|
-
if (namespace !== undefined)
|
|
958
|
-
effectiveArgs.push("--namespace", namespace);
|
|
959
|
-
effectiveArgs.push("--session", options.managedSessionName);
|
|
960
|
-
if (explicitNamespacePresent)
|
|
961
|
-
argsToAppend = stripExplicitNamespaceArgs(args);
|
|
962
|
-
managedSessionName = options.managedSessionName;
|
|
963
|
-
sessionName = options.managedSessionName;
|
|
964
|
-
usedImplicitSession = true;
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
else if (shouldCreateFreshManagedSession && commandNeedsManagedSession) {
|
|
968
|
-
if (namespace !== undefined)
|
|
969
|
-
effectiveArgs.push("--namespace", namespace);
|
|
970
|
-
effectiveArgs.push("--session", options.freshSessionName);
|
|
971
|
-
if (explicitNamespacePresent)
|
|
972
|
-
argsToAppend = stripExplicitNamespaceArgs(args);
|
|
973
|
-
managedSessionName = options.freshSessionName;
|
|
974
|
-
sessionName = options.freshSessionName;
|
|
975
|
-
}
|
|
976
|
-
if (commandInfo.command !== undefined && !sessionName && !explicitNamespacePresent) {
|
|
977
|
-
namespace = resolveAgentBrowserNamespace(args, getAgentBrowserProcessEnvironment().AGENT_BROWSER_NAMESPACE);
|
|
978
|
-
}
|
|
979
|
-
const targetsActiveManagedSession = options.managedSessionActive
|
|
980
|
-
&& commandNeedsManagedSession
|
|
981
|
-
&& sessionName
|
|
982
|
-
&& getAgentBrowserSessionIdentityKey(sessionName, namespace) === getAgentBrowserSessionIdentityKey(options.managedSessionName, options.managedSessionNamespace);
|
|
983
|
-
if (targetsActiveManagedSession && startupScopedFlags.length > 0 && !isCloseCommand(commandInfo.command) && !validationError) {
|
|
984
|
-
const recoveryArgs = explicitSessionName ? stripExplicitSessionArgs(args) : args;
|
|
985
|
-
recoveryHint = {
|
|
986
|
-
exampleArgs: recoveryArgs,
|
|
987
|
-
exampleParams: { args: recoveryArgs, sessionMode: "fresh" },
|
|
988
|
-
reason: `Launch-scoped flags (${LAUNCH_SCOPED_FLAG_LABEL}) need a fresh upstream launch once the extension-managed session is already active.`,
|
|
989
|
-
recommendedSessionMode: "fresh",
|
|
990
|
-
};
|
|
991
|
-
validationError = [
|
|
992
|
-
`The current extension-managed agent-browser session is already running, so launch-scoped flags ${startupScopedFlags.join(", ")} would replace or be ignored by upstream agent-browser.`,
|
|
993
|
-
explicitSessionName
|
|
994
|
-
? "Remove the explicit `--session` and retry with `sessionMode: \"fresh\"` to force a fresh upstream launch."
|
|
995
|
-
: "Retry this call with `sessionMode: \"fresh\"` to force a fresh upstream launch.",
|
|
996
|
-
].join(" ");
|
|
997
|
-
}
|
|
998
|
-
if (targetsActiveManagedSession && canUseHeadlessCompatibilityUserAgent(args)) {
|
|
999
|
-
if (requestedCompatibilityWorkaround && !options.managedSessionCompatibilityWorkaround && !validationError) {
|
|
1000
|
-
compatibilityWorkaround = undefined;
|
|
1001
|
-
const recoveryArgs = explicitSessionName ? stripExplicitSessionArgs(args) : args;
|
|
1002
|
-
recoveryHint = {
|
|
1003
|
-
exampleArgs: recoveryArgs,
|
|
1004
|
-
exampleParams: { args: recoveryArgs, sessionMode: "fresh" },
|
|
1005
|
-
reason: "The requested site compatibility user agent is launch-scoped and needs a fresh browser session.",
|
|
1006
|
-
recommendedSessionMode: "fresh",
|
|
1007
|
-
};
|
|
1008
|
-
validationError = explicitSessionName
|
|
1009
|
-
? "The current extension-managed agent-browser session is already running without the user agent required by this site. Remove the explicit `--session` and retry with `sessionMode: \"fresh\"` so the compatibility user agent is applied at launch."
|
|
1010
|
-
: "The current extension-managed agent-browser session is already running without the user agent required by this site. Retry this call with `sessionMode: \"fresh\"` so the compatibility user agent is applied at launch.";
|
|
1011
|
-
}
|
|
1012
|
-
else {
|
|
1013
|
-
compatibilityWorkaround = requestedCompatibilityWorkaround ?? options.managedSessionCompatibilityWorkaround;
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
if (compatibilityWorkaround && !targetsActiveManagedSession) {
|
|
118
|
+
export function buildExecutionPlan(inputArgs, options) {
|
|
119
|
+
const args = withNativeSession(inputArgs);
|
|
120
|
+
const startupScopedFlags = effectiveStartupFlags(args, options.managedSessionNamespace);
|
|
121
|
+
const descriptor = parseArgvDescriptor(args);
|
|
122
|
+
const commandInfo = descriptor.commandInfo;
|
|
123
|
+
if (isPlainTextInspectionArgs(args)) {
|
|
124
|
+
return inspectionPlan(args, commandInfo, startupScopedFlags);
|
|
125
|
+
}
|
|
126
|
+
const failure = planningFailure(args);
|
|
127
|
+
if (failure) {
|
|
128
|
+
return failure;
|
|
129
|
+
}
|
|
130
|
+
const needsSession = options.browserIndependentReadConfirmation !== true &&
|
|
131
|
+
needsManagedSession(descriptor, options.stdin);
|
|
132
|
+
const selection = selectExecutionSession(args, options, {
|
|
133
|
+
command: commandInfo.command,
|
|
134
|
+
needsManagedSession: needsSession,
|
|
135
|
+
startupScopedFlags,
|
|
136
|
+
});
|
|
137
|
+
const activeTarget = targetsActiveManagedSession(selection, options, needsSession);
|
|
138
|
+
const requested = getCompatibilityWorkaround(args, commandInfo);
|
|
139
|
+
const recovery = activeTarget
|
|
140
|
+
? activeLaunchRecovery(args, startupScopedFlags, commandInfo.command, selection)
|
|
141
|
+
: selection;
|
|
142
|
+
const compatibility = activeTarget
|
|
143
|
+
? activeCompatibilityPlan(args, requested, options.managedSessionCompatibilityWorkaround, recovery)
|
|
144
|
+
: { ...recovery, compatibilityWorkaround: requested };
|
|
145
|
+
const effectiveArgs = [...jsonPrefix(args), ...selection.prefixArgs];
|
|
146
|
+
if (compatibility.compatibilityWorkaround && !activeTarget) {
|
|
1017
147
|
effectiveArgs.push("--user-agent", getDefaultHeadlessCompatUserAgent());
|
|
1018
148
|
}
|
|
1019
|
-
effectiveArgs.push(...argsToAppend);
|
|
149
|
+
effectiveArgs.push(...selection.argsToAppend);
|
|
1020
150
|
return {
|
|
1021
151
|
commandInfo,
|
|
1022
|
-
compatibilityWorkaround,
|
|
152
|
+
compatibilityWorkaround: compatibility.compatibilityWorkaround,
|
|
1023
153
|
effectiveArgs,
|
|
1024
|
-
managedSessionName,
|
|
1025
|
-
namespace,
|
|
1026
|
-
plainTextInspection,
|
|
1027
|
-
recoveryHint,
|
|
1028
|
-
sessionName,
|
|
154
|
+
managedSessionName: selection.managedSessionName,
|
|
155
|
+
namespace: selection.namespace,
|
|
156
|
+
plainTextInspection: false,
|
|
157
|
+
recoveryHint: compatibility.recoveryHint,
|
|
158
|
+
sessionName: selection.sessionName,
|
|
1029
159
|
startupScopedFlags,
|
|
1030
|
-
usedImplicitSession,
|
|
1031
|
-
validationError,
|
|
160
|
+
usedImplicitSession: selection.usedImplicitSession,
|
|
161
|
+
validationError: compatibility.validationError,
|
|
1032
162
|
};
|
|
1033
163
|
}
|
|
1034
|
-
export function chooseOpenResultTabCorrection(options) {
|
|
1035
|
-
const normalizedTargetUrl = typeof options.targetUrl === "string" ? normalizeComparableUrl(options.targetUrl) : undefined;
|
|
1036
|
-
if (!normalizedTargetUrl) {
|
|
1037
|
-
return undefined;
|
|
1038
|
-
}
|
|
1039
|
-
const tabsWithIndices = options.tabs.map((tab, index) => ({
|
|
1040
|
-
...tab,
|
|
1041
|
-
index: typeof tab.index === "number" ? tab.index : index,
|
|
1042
|
-
label: normalizeTabSelectionValue(tab.label),
|
|
1043
|
-
tabId: normalizeTabSelectionValue(tab.tabId),
|
|
1044
|
-
}));
|
|
1045
|
-
const activeTab = tabsWithIndices.find((tab) => tab.active === true) ??
|
|
1046
|
-
(typeof options.activeTabIndex === "number" ? tabsWithIndices.find((tab) => tab.index === options.activeTabIndex) : undefined);
|
|
1047
|
-
if (activeTab && normalizeComparableUrl(activeTab.url ?? "") === normalizedTargetUrl) {
|
|
1048
|
-
return undefined;
|
|
1049
|
-
}
|
|
1050
|
-
const matchingTabs = tabsWithIndices.filter((tab) => normalizeComparableUrl(tab.url ?? "") === normalizedTargetUrl);
|
|
1051
|
-
if (matchingTabs.length === 0) {
|
|
1052
|
-
return undefined;
|
|
1053
|
-
}
|
|
1054
|
-
const trimmedTargetTitle = typeof options.targetTitle === "string" ? options.targetTitle.trim() : "";
|
|
1055
|
-
const titledMatch = trimmedTargetTitle.length === 0
|
|
1056
|
-
? undefined
|
|
1057
|
-
: matchingTabs.find((tab) => typeof tab.title === "string" && tab.title.trim() === trimmedTargetTitle);
|
|
1058
|
-
const selectedTab = titledMatch ?? matchingTabs[0];
|
|
1059
|
-
const tabSelection = extractTabSelection(selectedTab);
|
|
1060
|
-
return tabSelection
|
|
1061
|
-
? {
|
|
1062
|
-
...tabSelection,
|
|
1063
|
-
targetTitle: trimmedTargetTitle.length > 0 ? trimmedTargetTitle : undefined,
|
|
1064
|
-
targetUrl: normalizedTargetUrl,
|
|
1065
|
-
}
|
|
1066
|
-
: undefined;
|
|
1067
|
-
}
|