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
|
@@ -4,22 +4,29 @@ const observation = new AsyncLocalStorage();
|
|
|
4
4
|
export function getNativeWebMcpCatalog(data) {
|
|
5
5
|
if (Array.isArray(data)) {
|
|
6
6
|
for (let index = data.length - 1; index >= 0; index -= 1) {
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const row = data[index];
|
|
8
|
+
const catalog = getNativeWebMcpCatalog(isRecord(row) ? row.result : undefined);
|
|
9
|
+
if (catalog) {
|
|
9
10
|
return catalog;
|
|
11
|
+
}
|
|
10
12
|
}
|
|
11
13
|
}
|
|
12
|
-
if (!isRecord(data) || !isRecord(data.webmcp))
|
|
14
|
+
if (!isRecord(data) || !isRecord(data.webmcp)) {
|
|
13
15
|
return undefined;
|
|
14
|
-
|
|
16
|
+
}
|
|
17
|
+
return Array.isArray(data.webmcp.tools) || data.webmcp.status === "unavailable"
|
|
18
|
+
? data.webmcp
|
|
19
|
+
: undefined;
|
|
15
20
|
}
|
|
16
21
|
export function observeNativeWebMcp(data) {
|
|
17
22
|
const current = observation.getStore();
|
|
18
|
-
if (!current)
|
|
23
|
+
if (!current) {
|
|
19
24
|
return;
|
|
25
|
+
}
|
|
20
26
|
const catalog = getNativeWebMcpCatalog(data);
|
|
21
|
-
if (catalog)
|
|
27
|
+
if (catalog) {
|
|
22
28
|
current.catalog = catalog;
|
|
29
|
+
}
|
|
23
30
|
}
|
|
24
31
|
/** Native discovery is edge-triggered; helper reads must not swallow its updates. */
|
|
25
32
|
export async function collectNativeWebMcp(run) {
|
|
@@ -3,42 +3,46 @@ import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
|
3
3
|
import { isMainThread } from "node:worker_threads";
|
|
4
4
|
import pathKey from "path-key";
|
|
5
5
|
import which from "which";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
6
|
+
import { isRecord } from "./parsing.js";
|
|
7
|
+
function environmentValues(env, name) {
|
|
8
|
+
return Object.entries(env)
|
|
9
|
+
.filter(([key, value]) => key.toUpperCase() === name && value !== undefined)
|
|
10
|
+
.map(([, value]) => value);
|
|
11
|
+
}
|
|
12
|
+
function hasStockEnvironment(env) {
|
|
13
|
+
const paths = environmentValues(env, "PATH");
|
|
14
|
+
const extensions = environmentValues(env, "PATHEXT");
|
|
15
|
+
return (paths.length === 1 &&
|
|
16
|
+
paths.at(0) !== undefined &&
|
|
17
|
+
paths.at(0) !== "" &&
|
|
18
|
+
extensions.length === 1 &&
|
|
19
|
+
extensions.at(0) === process.env.PATHEXT &&
|
|
20
|
+
environmentValues(env, "NODEFAULTCURRENTDIRECTORYINEXEPATH").length === 0);
|
|
21
|
+
}
|
|
22
|
+
function hasNativeCommandShell() {
|
|
23
|
+
const { comspec, SystemRoot } = process.env;
|
|
24
|
+
if (comspec === undefined ||
|
|
25
|
+
comspec.length === 0 ||
|
|
26
|
+
!isAbsolute(comspec) ||
|
|
27
|
+
SystemRoot === undefined ||
|
|
28
|
+
SystemRoot.length === 0) {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
24
31
|
try {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const native = statSync(join(process.env.SystemRoot, "System32", "cmd.exe"), { bigint: true });
|
|
29
|
-
if (shell.dev !== native.dev || shell.ino !== native.ino)
|
|
30
|
-
return undefined;
|
|
32
|
+
const shell = statSync(comspec, { bigint: true });
|
|
33
|
+
const native = statSync(join(SystemRoot, "System32", "cmd.exe"), { bigint: true });
|
|
34
|
+
return shell.dev === native.dev && shell.ino === native.ino;
|
|
31
35
|
}
|
|
32
36
|
catch {
|
|
33
|
-
return
|
|
37
|
+
return false;
|
|
34
38
|
}
|
|
39
|
+
}
|
|
40
|
+
function selectLauncher(cwd, env) {
|
|
35
41
|
const previousCwd = process.cwd();
|
|
36
|
-
let selected;
|
|
37
42
|
try {
|
|
38
|
-
// which 2 has no cwd option
|
|
39
|
-
// synchronous resolution, restoring it before any caller can await.
|
|
43
|
+
// which 2 has no cwd option; synchronous resolution matches cross-spawn's child cwd.
|
|
40
44
|
process.chdir(cwd);
|
|
41
|
-
|
|
45
|
+
return which.sync("agent-browser", { path: env[pathKey({ env })], nothrow: true });
|
|
42
46
|
}
|
|
43
47
|
catch {
|
|
44
48
|
return undefined;
|
|
@@ -46,21 +50,25 @@ export function resolveWindowsStockLauncher(cwd, env) {
|
|
|
46
50
|
finally {
|
|
47
51
|
process.chdir(previousCwd);
|
|
48
52
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return undefined;
|
|
53
|
+
}
|
|
54
|
+
function stockLauncherBinary(absoluteShim) {
|
|
52
55
|
try {
|
|
53
|
-
|
|
54
|
-
const absoluteShim = resolve(cwd, selected);
|
|
55
|
-
if (statSync(absoluteShim).size > 512)
|
|
56
|
+
if (statSync(absoluteShim).size > 512) {
|
|
56
57
|
return undefined;
|
|
58
|
+
}
|
|
57
59
|
const text = readFileSync(absoluteShim, "utf8");
|
|
58
|
-
if (!/^@ECHO off\r?\n"%~dp0node_modules\\agent-browser\\bin\\agent-browser-win32-x64\.exe" %\*(?:\r?\n)?(?![\s\S])/.test(text))
|
|
60
|
+
if (!/^@ECHO off\r?\n"%~dp0node_modules\\agent-browser\\bin\\agent-browser-win32-x64\.exe" %\*(?:\r?\n)?(?![\s\S])/.test(text)) {
|
|
59
61
|
return undefined;
|
|
62
|
+
}
|
|
60
63
|
const packageRoot = join(dirname(absoluteShim), "node_modules", "agent-browser");
|
|
61
64
|
const manifest = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
|
|
62
|
-
if (manifest.name !== "agent-browser" || !
|
|
65
|
+
if (!isRecord(manifest) || manifest.name !== "agent-browser" || !isRecord(manifest.bin)) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const entrypoint = manifest.bin["agent-browser"];
|
|
69
|
+
if (entrypoint !== "bin/agent-browser.js" && entrypoint !== "./bin/agent-browser.js") {
|
|
63
70
|
return undefined;
|
|
71
|
+
}
|
|
64
72
|
const binary = join(packageRoot, "bin", "agent-browser-win32-x64.exe");
|
|
65
73
|
return statSync(binary).isFile() ? binary : undefined;
|
|
66
74
|
}
|
|
@@ -68,3 +76,21 @@ export function resolveWindowsStockLauncher(cwd, env) {
|
|
|
68
76
|
return undefined;
|
|
69
77
|
}
|
|
70
78
|
}
|
|
79
|
+
/** Bypass only upstream's optimized npm CMD shim: cmd.exe loses literal CR/LF.
|
|
80
|
+
* Keep which/path-key aligned with cross-spawn's public dependency versions.
|
|
81
|
+
* Unknown/custom launchers stay on cross-spawn.
|
|
82
|
+
*/
|
|
83
|
+
export function resolveWindowsStockLauncher(cwd, env) {
|
|
84
|
+
if (process.platform !== "win32" ||
|
|
85
|
+
!isMainThread ||
|
|
86
|
+
!hasStockEnvironment(env) ||
|
|
87
|
+
!hasNativeCommandShell()) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const selected = selectLauncher(cwd, env);
|
|
91
|
+
// cross-spawn's extensionless lookup cannot select this CMD shim.
|
|
92
|
+
if (selected === undefined || selected === null || !selected.toLowerCase().endsWith(".cmd")) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
return stockLauncherBinary(resolve(cwd, selected));
|
|
96
|
+
}
|
|
@@ -2,8 +2,9 @@ import { randomBytes } from "node:crypto";
|
|
|
2
2
|
import { createContext, runInContext, Script } from "node:vm";
|
|
3
3
|
function parseLimit(value, label) {
|
|
4
4
|
const parsed = Number(value);
|
|
5
|
-
if (!Number.isSafeInteger(parsed) || parsed <= 0)
|
|
5
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
6
6
|
throw new Error(`Invalid ${label}.`);
|
|
7
|
+
}
|
|
7
8
|
return parsed;
|
|
8
9
|
}
|
|
9
10
|
const maxMessageBytes = parseLimit(process.argv[2], "script IPC message limit");
|
|
@@ -11,7 +12,8 @@ const maxCumulativeBytes = parseLimit(process.argv[3], "script IPC cumulative li
|
|
|
11
12
|
let cumulativeBytes = 0;
|
|
12
13
|
let inputBuffer = Buffer.alloc(0);
|
|
13
14
|
let started = false;
|
|
14
|
-
const sandbox =
|
|
15
|
+
const sandbox = {};
|
|
16
|
+
Object.setPrototypeOf(sandbox, null);
|
|
15
17
|
const context = createContext(sandbox, {
|
|
16
18
|
codeGeneration: { strings: false, wasm: false },
|
|
17
19
|
name: "agent-browser-script",
|
|
@@ -19,11 +21,13 @@ const context = createContext(sandbox, {
|
|
|
19
21
|
const bridgeKey = `__piab_send_${randomBytes(16).toString("hex")}`;
|
|
20
22
|
const stateName = `__piab_state_${randomBytes(16).toString("hex")}`;
|
|
21
23
|
const hostSend = (json) => {
|
|
22
|
-
if (typeof json !== "string")
|
|
24
|
+
if (typeof json !== "string") {
|
|
23
25
|
return false;
|
|
26
|
+
}
|
|
24
27
|
const bytes = Buffer.byteLength(json, "utf8") + 1;
|
|
25
|
-
if (bytes > maxMessageBytes || cumulativeBytes + bytes > maxCumulativeBytes)
|
|
28
|
+
if (bytes > maxMessageBytes || cumulativeBytes + bytes > maxCumulativeBytes) {
|
|
26
29
|
return false;
|
|
30
|
+
}
|
|
27
31
|
cumulativeBytes += bytes;
|
|
28
32
|
try {
|
|
29
33
|
process.stdout.write(`${json}\n`);
|
|
@@ -36,10 +40,16 @@ const hostSend = (json) => {
|
|
|
36
40
|
Object.setPrototypeOf(hostSend, null);
|
|
37
41
|
Object.freeze(hostSend);
|
|
38
42
|
sandbox[bridgeKey] = hostSend;
|
|
39
|
-
runInContext("const " +
|
|
43
|
+
runInContext("const " +
|
|
44
|
+
stateName +
|
|
45
|
+
" = (() => {\n" +
|
|
40
46
|
" 'use strict';\n" +
|
|
41
|
-
" const send = globalThis[" +
|
|
42
|
-
|
|
47
|
+
" const send = globalThis[" +
|
|
48
|
+
JSON.stringify(bridgeKey) +
|
|
49
|
+
"];\n" +
|
|
50
|
+
" delete globalThis[" +
|
|
51
|
+
JSON.stringify(bridgeKey) +
|
|
52
|
+
"];\n" +
|
|
43
53
|
" for (const name of ['console','process','require','Buffer','fetch','WebSocket','setTimeout','setInterval','setImmediate','queueMicrotask','clearTimeout','clearInterval','clearImmediate']) Object.defineProperty(globalThis, name, { value: undefined, writable: false, configurable: false });\n" +
|
|
44
54
|
" const NativePromise = Promise;\n" +
|
|
45
55
|
" const promiseThen = Promise.prototype.then;\n" +
|
|
@@ -47,7 +57,9 @@ runInContext("const " + stateName + " = (() => {\n" +
|
|
|
47
57
|
" const pending = new Map();\n" +
|
|
48
58
|
" let nextId = 0;\n" +
|
|
49
59
|
" const encode = (value) => { const json = JSON.stringify(value); if (typeof json !== 'string') throw new TypeError('Value must be JSON-serializable.'); return json; };\n" +
|
|
50
|
-
" const sendValue = (value) => { const json = encode(value); if (json.length + 1 > " +
|
|
60
|
+
" const sendValue = (value) => { const json = encode(value); if (json.length + 1 > " +
|
|
61
|
+
String(maxMessageBytes) +
|
|
62
|
+
" || send(json) !== true) throw new RangeError('Script IPC limit exceeded.'); };\n" +
|
|
51
63
|
" const browser = function browser(params) {\n" +
|
|
52
64
|
" return new NativePromise((resolve, reject) => {\n" +
|
|
53
65
|
" const id = ++nextId;\n" +
|
|
@@ -91,18 +103,67 @@ runInContext("const " + stateName + " = (() => {\n" +
|
|
|
91
103
|
" });\n" +
|
|
92
104
|
"})();", context, { timeout: 1_000 });
|
|
93
105
|
const deliver = runInContext(`${stateName}.deliver`, context, { timeout: 1_000 });
|
|
106
|
+
if (typeof deliver !== "function") {
|
|
107
|
+
throw new Error("Script response bridge was not initialized.");
|
|
108
|
+
}
|
|
94
109
|
function fail(name, message) {
|
|
95
110
|
hostSend(JSON.stringify({ type: "complete", error: { name, message } }));
|
|
96
111
|
}
|
|
97
112
|
function describeError(error, fallback) {
|
|
98
|
-
if (
|
|
113
|
+
if (error === null || typeof error !== "object") {
|
|
99
114
|
return { message: fallback, name: "Error" };
|
|
100
|
-
|
|
115
|
+
}
|
|
116
|
+
const message = "message" in error ? error.message : undefined;
|
|
117
|
+
const name = "name" in error ? error.name : undefined;
|
|
101
118
|
return {
|
|
102
|
-
message: typeof
|
|
103
|
-
name: typeof
|
|
119
|
+
message: typeof message === "string" ? message.replace(/[\r\n]+/g, " ").slice(0, 400) : fallback,
|
|
120
|
+
name: typeof name === "string" ? name.slice(0, 80) : "Error",
|
|
104
121
|
};
|
|
105
122
|
}
|
|
123
|
+
function startScript(message) {
|
|
124
|
+
if (message === null ||
|
|
125
|
+
typeof message !== "object" ||
|
|
126
|
+
!("type" in message) ||
|
|
127
|
+
message.type !== "start" ||
|
|
128
|
+
!("code" in message) ||
|
|
129
|
+
typeof message.code !== "string") {
|
|
130
|
+
fail("Error", "Invalid script start message.");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
started = true;
|
|
134
|
+
try {
|
|
135
|
+
const source = `'use strict';\n${stateName}.run(async function () {\n'use strict';\n${message.code}\n});`;
|
|
136
|
+
const script = new Script(source, {
|
|
137
|
+
filename: "agent-browser-script.js",
|
|
138
|
+
importModuleDynamically() {
|
|
139
|
+
process.exit(70);
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
script.runInContext(context);
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
const described = describeError(error, "Script compilation failed.");
|
|
146
|
+
fail(described.name, described.message);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
function deliverBrowserResponse(message, line) {
|
|
150
|
+
if (message === null ||
|
|
151
|
+
typeof message !== "object" ||
|
|
152
|
+
!("type" in message) ||
|
|
153
|
+
message.type !== "response") {
|
|
154
|
+
fail("Error", "Invalid parent IPC response.");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
if (typeof deliver !== "function") {
|
|
159
|
+
throw new Error("Script response bridge is unavailable.");
|
|
160
|
+
}
|
|
161
|
+
Reflect.apply(deliver, undefined, [line]);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
fail("Error", "Invalid browser response envelope.");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
106
167
|
function handleLine(line) {
|
|
107
168
|
const bytes = Buffer.byteLength(line, "utf8") + 1;
|
|
108
169
|
if (bytes > maxMessageBytes || cumulativeBytes + bytes > maxCumulativeBytes) {
|
|
@@ -119,37 +180,10 @@ function handleLine(line) {
|
|
|
119
180
|
return;
|
|
120
181
|
}
|
|
121
182
|
if (!started) {
|
|
122
|
-
|
|
123
|
-
fail("Error", "Invalid script start message.");
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
started = true;
|
|
127
|
-
try {
|
|
128
|
-
const source = `'use strict';\n${stateName}.run(async function () {\n'use strict';\n${message.code}\n});`;
|
|
129
|
-
const script = new Script(source, {
|
|
130
|
-
filename: "agent-browser-script.js",
|
|
131
|
-
importModuleDynamically() {
|
|
132
|
-
process.exit(70);
|
|
133
|
-
},
|
|
134
|
-
});
|
|
135
|
-
script.runInContext(context, { timeout: undefined });
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
const described = describeError(error, "Script compilation failed.");
|
|
139
|
-
fail(described.name, described.message);
|
|
140
|
-
}
|
|
183
|
+
startScript(message);
|
|
141
184
|
return;
|
|
142
185
|
}
|
|
143
|
-
|
|
144
|
-
fail("Error", "Invalid parent IPC response.");
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
try {
|
|
148
|
-
deliver(line);
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
fail("Error", "Invalid browser response envelope.");
|
|
152
|
-
}
|
|
186
|
+
deliverBrowserResponse(message, line);
|
|
153
187
|
}
|
|
154
188
|
process.stdin.on("data", (rawChunk) => {
|
|
155
189
|
const chunk = Buffer.isBuffer(rawChunk) ? rawChunk : Buffer.from(rawChunk);
|
|
@@ -161,12 +195,15 @@ process.stdin.on("data", (rawChunk) => {
|
|
|
161
195
|
}
|
|
162
196
|
for (;;) {
|
|
163
197
|
const newline = inputBuffer.indexOf(10);
|
|
164
|
-
if (newline < 0)
|
|
198
|
+
if (newline < 0) {
|
|
165
199
|
break;
|
|
200
|
+
}
|
|
166
201
|
const line = inputBuffer.subarray(0, newline).toString("utf8");
|
|
167
202
|
inputBuffer = inputBuffer.subarray(newline + 1);
|
|
168
203
|
handleLine(line);
|
|
169
204
|
}
|
|
170
205
|
});
|
|
171
|
-
process.stdin.on("error", () =>
|
|
206
|
+
process.stdin.on("error", () => {
|
|
207
|
+
// Parent transport teardown is handled by the parent's worker lifecycle owner.
|
|
208
|
+
});
|
|
172
209
|
hostSend(JSON.stringify({ type: "ready" }));
|
|
@@ -11,11 +11,13 @@ function stableVersionParts(version) {
|
|
|
11
11
|
export function isSupportedAgentBrowserVersion(version) {
|
|
12
12
|
const actual = stableVersionParts(version);
|
|
13
13
|
const minimum = stableVersionParts(MINIMUM_AGENT_BROWSER_VERSION);
|
|
14
|
-
if (!actual || !minimum)
|
|
14
|
+
if (!actual || !minimum) {
|
|
15
15
|
return false;
|
|
16
|
+
}
|
|
16
17
|
for (let index = 0; index < minimum.length; index += 1) {
|
|
17
|
-
if (actual[index] !== minimum[index])
|
|
18
|
+
if (actual[index] !== minimum[index]) {
|
|
18
19
|
return actual[index] > minimum[index];
|
|
20
|
+
}
|
|
19
21
|
}
|
|
20
22
|
return true;
|
|
21
23
|
}
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Architecture
|
|
2
2
|
|
|
3
3
|
Related docs:
|
|
4
|
+
|
|
4
5
|
- [`../README.md`](../README.md)
|
|
5
6
|
- [`../AGENTS.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/AGENTS.md) (maintainer workflows, including upstream capability baseline)
|
|
6
7
|
- [`REQUIREMENTS.md`](REQUIREMENTS.md)
|
|
@@ -13,6 +14,8 @@ Build this as a **thin `pi` extension/package** that exposes native commands and
|
|
|
13
14
|
|
|
14
15
|
The package install path is the primary product path. Local checkout development should use explicit CLI loading for isolated smoke tests and configured-source plain `pi` runs for lifecycle validation, while package-manifest behavior and packaged contents matter more.
|
|
15
16
|
|
|
17
|
+
Runtime graphs that use Pi host APIs are statically imported through Pi's extension loader, which supplies the host-peer mapping. Native ESM lazy imports must not bypass that mapping: a runtime-only global package does not install its optional Pi peers. The browser runner and observation/image publication retain Pi's native image primitives without a package-owned resolver or bundled host.
|
|
18
|
+
|
|
16
19
|
## Chosen shape
|
|
17
20
|
|
|
18
21
|
### Compact tools and native discovery
|
|
@@ -30,6 +33,7 @@ The collector's dynamic `isManaged()` decides ownership. Managed Pi delivers ful
|
|
|
30
33
|
### Direct subprocess execution
|
|
31
34
|
|
|
32
35
|
The extension should:
|
|
36
|
+
|
|
33
37
|
- resolve `agent-browser` from `PATH`
|
|
34
38
|
- invoke it with native Node `spawn` on POSIX and `cross-spawn` on Windows. For the recognized global npm CMD template, public `which`/`path-key` resolution selects the same launcher and Node invokes its exact adjacent native executable directly, preserving literal CR/LF. Recognition requires the stock template, package identity and executable; custom launchers, other layouts, ambiguous search environments and worker-thread calls retain `cross-spawn`. No later installation is substituted. Custom or unrecognized batch files can still truncate literal newlines. Caller commands and helper probes retain empty operands, literal doublequotes, command/subcommand adjacency and explicit default `--namespace ""`. Keep piped stdin/stdout/stderr and await full Windows process-tree termination with `taskkill /T /F` on timeout or abort before falling back to the direct child signal. Missing commands use the spawner's `ENOENT`
|
|
35
39
|
- bound native process-identity queries at ten seconds on Windows, including PowerShell startup, and five seconds on POSIX. These probes preserve PID/start-time comparison and fail closed when identity is unavailable; their budget is separate from lock contention and browser command watchdogs
|
|
@@ -42,7 +46,7 @@ The extension should:
|
|
|
42
46
|
|
|
43
47
|
### Persistent browser code
|
|
44
48
|
|
|
45
|
-
`lib/input-modes/script.ts` and compiled `script-worker.js` retain the fresh permissioned Node child/VM and JSON-lines bridge. The internal filenames are not a public `script` input. `
|
|
49
|
+
`lib/input-modes/script.ts` and compiled `script-worker.js` retain the fresh permissioned Node child/VM and JSON-lines bridge. The internal filenames are not a public `script` input. `orchestration/extension-code.ts` selects the ordinary browser identity in the parent, holds its shared execution lock for the whole cell, serializes inner requests through the same executor, and reaps the child on completion, timeout, abort, branch change, or shutdown. The browser survives cell completion according to existing ownership. Native auth, profiles, state, connect, batch, and local commands retain ordinary parent-side configuration/environment; only changing the fixed session/namespace and namespace-wide close are excluded from an inner call.
|
|
46
50
|
|
|
47
51
|
The child has an empty environment, Node permission mode without host capability allowlists, a 64 MiB heap ceiling, and a VM with string/WebAssembly code generation disabled. Null-prototype `browser`, `emit`, and `emitImage` functions use JSON-only IPC; parent promises/objects/functions are not exposed. There are no imports or host filesystem/network/process/timer APIs. Node's VM alone is not a security boundary. The retained child isolation is distinct from the selected browser's persistent authentication and native capabilities; no QuickJS, broker, second driver, or provider payload injection is involved.
|
|
48
52
|
|
|
@@ -73,6 +77,7 @@ Artifact directory preparation has one filesystem-error boundary inside the exis
|
|
|
73
77
|
The primary UX is the agent calling the tool directly.
|
|
74
78
|
|
|
75
79
|
That means:
|
|
80
|
+
|
|
76
81
|
- no command-heavy slash-command interface
|
|
77
82
|
- no manual user orchestration as the main workflow
|
|
78
83
|
- any future slash commands should be minimal and secondary
|
|
@@ -119,6 +124,7 @@ Local checkout validation has two intentional modes:
|
|
|
119
124
|
The repo should not add a repo-local `.pi/extensions/` autoload shim as the documented checkout path.
|
|
120
125
|
|
|
121
126
|
Why:
|
|
127
|
+
|
|
122
128
|
- avoids duplicate `agent_browser` registrations when the package is also installed globally
|
|
123
129
|
- keeps the product contract centered on the package manifest instead of repo-local autoload wiring
|
|
124
130
|
- keeps reload and exact-session relaunch validation tied to Pi's configured-source lifecycle instead of an explicit-extension quick-test path, while `session_tree` state changes stay covered by focused extension harness tests
|
|
@@ -128,7 +134,7 @@ The published package should exclude agent-only and internal planning materials
|
|
|
128
134
|
|
|
129
135
|
## Host execution hook
|
|
130
136
|
|
|
131
|
-
The default extension factory optionally accepts `{ beforeExecute }`. `
|
|
137
|
+
The default extension factory optionally accepts `{ beforeExecute }`. `orchestration/extension-command-admission.ts` awaits this host callback after input resolution and before ordinary dispatch, forwarding the original outer Pi tool-call ID through inner code calls and supplying each dispatch's signal. Configured hosts use Pi's native sequential tool scheduling; inner code calls retain the existing serial queue. No separate controller, persistence store, retry policy, or timeout is introduced. Ordinary installation, internal helper probes, cleanup, batch-row execution, and web search are unchanged. See [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#host-execution-hook) for cancellation and error behavior; `test/agent-browser.pi-pipeline.test.ts` exercises the registered factory through real Pi with a fake upstream executable.
|
|
132
138
|
|
|
133
139
|
## Session model
|
|
134
140
|
|
|
@@ -141,6 +147,7 @@ An explicit native `session` default (user/project JSON or `AGENT_BROWSER_SESSIO
|
|
|
141
147
|
When no native session, attachment, or explicit fresh launch is selected, `sessionMode: "auto"` uses `pi-root-<sha256(root Pi ID)[0:24]>` through the existing caller-owned named-session path. Descendants receive `PI_SUBAGENT_ROOT_SESSION_ID` from pi-subagents; root processes use `ctx.sessionManager.getSessionId()`. No cwd, human fork ancestry, run registry, or process-global assignment participates. The same name is the default native restore key. Existing native daemon inspection runs inside the existing identity queue: inactive roots receive bootstrap defaults, while active roots retain native launch settings and their current restore key. Scoped subprocess environment keeps helper settings consistent; no launch-settings journal is added. Root-name explicit follow-ups retain those defaults; unrelated explicit names do not. Global/override package `browser.defaultProfile` with `policy: "always"` supplies native Chrome profile names only, plus the configured executable, only when the effective engine is Chrome. Paths and project-only profile settings stay advisory. Native config/environment and explicit launch settings win. The communal source is copied by native Chrome launch, never by the wrapper, and each root's restore writes remain separate. Native JSON restore omits IndexedDB, service workers, and page-memory credentials; application-level restart verification is required. Parent and child quit leave the root browser alive; shared execution locks coordinate updated cooperating processes without a broker. An active older/fresh managed session keeps its existing lifecycle. A configured session has the same precedence over `fresh` as a literal `--session`; code follows the selected ordinary browser lifecycle; Electron launch retains its owned lifecycle. Electron launch suppresses the native session environment default only while allocating its generated session; ordinary browser follow-ups still honor the configured native default, so use the returned Electron session explicitly.
|
|
142
148
|
|
|
143
149
|
Why:
|
|
150
|
+
|
|
144
151
|
- works out of the box
|
|
145
152
|
- gives continuity across calls
|
|
146
153
|
- avoids forcing the agent to invent session names for basic browsing
|
|
@@ -168,6 +175,7 @@ The tool should also expose a first-class `sessionMode: "fresh"` escape hatch so
|
|
|
168
175
|
### Ownership
|
|
169
176
|
|
|
170
177
|
Ownership rule:
|
|
178
|
+
|
|
171
179
|
- automatic root sessions use native caller-owned lifecycle; group members coordinate and close them explicitly
|
|
172
180
|
- older implicit auto-generated sessions are extension-managed convenience sessions
|
|
173
181
|
- unnamed `sessionMode: "fresh"` launches rotate that extension-managed session to a new upstream browser
|
|
@@ -175,6 +183,7 @@ Ownership rule:
|
|
|
175
183
|
- extension-managed sessions should be reusable during an active `pi` session and across `/reload`, exact-session relaunch, `/resume`, and Pi branch-tree transitions, while still being cleaned up predictably
|
|
176
184
|
|
|
177
185
|
Practical policy:
|
|
186
|
+
|
|
178
187
|
- preserve the current branch-visible extension-managed session across `/reload`, exact-session relaunch, `/resume`, and Pi 1.0.0+ `session_tree` branch transitions so persisted sessions can keep following the live browser after lifecycle changes
|
|
179
188
|
- close the active extension-managed session when the originating `pi` process quits, while leaving explicit caller-provided sessions alone
|
|
180
189
|
- after branch restore, use the existing locked daemon inspection to distinguish a confirmed inactive wrapper-owned daemon from a live, unknown, or unavailable one. For compatible automatic managed restore only, keep the pending reopen in ordered session page state and persist it as `sessionTabReopenPending`. Non-page calls such as `tab list` can start a daemon without fulfilling it; explicit HTTP reads leave the managed browser and pending reopen untouched, including across branch/reload replay. Before the first current-page operation (`get url`, history commands and relative `pushstate` included), reopen the complete recorded URL with native `open`, invalidate old refs with the existing `page-transition` state, and verify the actual tab. Explicit URL reads and all-read batches skip managed ownership changes and browser helpers entirely; native owns their HTTP fetch and validation. Native `open` resets frame scope. Consume the obligation on that attempt or an executed explicit context/navigation/close command, not an unreached batch row; a failed open does not permit repeated navigation of a now-live browser. After the reopen CLI starts, cancellation returns a structured `aborted` result through the ordinary result path with the exact namespace/session, consumed marker and ref invalidation; it does not throw away replay state or run later browser helpers. Cancellation before the CLI starts does not consume the pending reopen. Internal URLs retain their fragments while tab/ref comparisons remain fragment-insensitive and presentation keeps normal redaction. Older transcripts cannot recover a fragment they did not record. Caller-owned/attached browsers and restore-disabled sessions do not take this path; live wrong-tab recovery still only selects an existing target. Reopening reloads the URL, not unsaved forms, JavaScript memory, or history. There is no second restore store or lifecycle lock.
|
|
@@ -188,6 +197,7 @@ Practical policy:
|
|
|
188
197
|
- record successful `connect`, `--cdp`, enabled `--auto-connect`, environment-configured CDP/auto-connect, and wrapper Electron attachment identities in branch-visible state. First-use and later content-bearing calls live-check `get url` because attached targets can drift outside Pi. Caller config, file access, launch arguments, and environment pass through unchanged; only wrapper-injected compatibility launch arguments are omitted on active attachments. A terminal successful close removes the marker; a close followed by a later step whose lifecycle reports a browser launch preserves it, while a non-launching diagnostic such as `stream status` leaves the close terminal
|
|
189
198
|
- when a successful close targets the current extension-managed session, including an explicit `--session <current> close` or an `electron.cleanup` managed-session step, clear page/ref state, mark that session inactive, untrack cleanup ownership, and rotate the next default auto call to a fresh wrapper-generated session name rather than reusing the closed name
|
|
190
199
|
- on non-quit shutdown such as `/reload`, close off-branch owned managed sessions and off-branch owned Electron launches before clearing process-local ownership, but preserve the current branch-visible active managed session and Electron launch plus that launch's isolated `userDataDir` so reload continuity still works from the active transcript branch. First reuse of a restored Electron attachment checks the recorded namespace/session, live PID/profile presence, and exact browser WebSocket identity against current CDP metadata, then uses upstream `get cdp-url` to verify that the named daemon still targets that browser or one of its current pages. The metadata probe cannot commit daemon provenance merely by spawning; only a matching result permits the existing policy to record it. Ordinary calls, status, and probe share this path under the existing lock. Generic restore-disabled sessions, mismatched connections, quit, and off-branch cleanup are unchanged
|
|
200
|
+
- require a nonempty, non-whitespace `Browser`/`browser` string in `/json/version` for Electron CDP readiness and debug-port liveness; other version metadata is optional. Before signaling a live restored Electron PID without a tracked child handle, require the process start identity recorded at launch to match the live process (the same `process-identity.ts` PID-reuse proof used for execution claims and temp-root ownership); a missing, unreadable, or mismatched identity retains the process/profile
|
|
191
201
|
- expose still-owned off-branch Electron launch records to `electron.status { launchId }`, `electron.status { all: true }`, `electron.probe { launchId }`, and `electron.cleanup`, while leaving default `electron.probe` scoped to the current managed session
|
|
192
202
|
- if an unnamed fresh launch replaces an active extension-managed session, best-effort close the old managed session after the switch succeeds; `managedSessionOutcome.replacedSessionClosed` records whether that cleanup succeeded, and a failed close keeps the older identity wrapper-owned across transcript resume for explicit follow-up or cleanup
|
|
193
203
|
- expose `details.browserWindow` and one visible login handoff only when a successful first/fresh local wrapper-managed headed result, including `batch`, is not an attachment and has upstream `lifecycle.effectiveLaunch.browserLaunched: true` and a `created`/`replaced` managed-session outcome. Keep `visibility: "unverified"`: this is launch evidence, never a claim about the user's OS desktop
|
|
@@ -196,12 +206,12 @@ Practical policy:
|
|
|
196
206
|
- once the wrapper observes tab-drift risk for a session (profile restore correction, overlapping stale opens, or restored session state), later active-tab commands verify the intended tab under the existing session queue before semantic/ref helpers and user commands. Targets retain native CDP `targetId` across transcript replay; exact identity distinguishes duplicate URL/title tabs, while older targets without an ID keep URL-based matching. A cold managed reopen replaces the old ID. Native selection runs only when the intended tab is not already active, because upstream selection clears refs and frame scope even on same-tab reselection. Missing targets, failed selection, and post-selection target mismatches fail before user commands. Caller argv/stdin and native `--pin-tab` / `--no-pin-tab` preferences remain unchanged. Local commands, live `get url`, explicit HTTP `read <url>` (including its flags), URL `a11y`/`vitals`/`web-vitals`, `diff url`, `window new`, URL-bearing recording commands, and explicit tab/navigation/`connect`/`state load` recovery do not require the old target; history back/forward/reload, `pushstate`, and page-content operations still do. The same classifier scans effective batch rows past non-page prefixes until a page dependency or explicit context change, without rewriting user rows or changing bail behavior. For `window new` and `diff url`, observe the resulting URL instead of retaining the old target or treating the requested second URL as redirect evidence. Fold only reached native batch rows when available, discard targets before failed navigation/context transitions and live-verify the final page, discard observations and refs from before window/diff transitions, and let later successful snapshots rebuild refs even when another batch row fails. Retain an observed blank destination after either command instead of recovering the old page; if no final target is observed, use the existing unknown-target state. Caller batch arguments, stdin and bail behavior stay unchanged. Successful batches containing navigation-observable actions use the same final live page/identity observation as direct actions, so same-address popup tabs replace the pre-batch target before later pinning. Terminal batch closes do not trigger a page probe, and pending WebMCP targets remain unknown. Routine same-session commands avoid `tab list` preflights
|
|
197
207
|
- for sessions with observed tab-drift risk, after a successful command on a known tab target, the wrapper may best-effort restore that same target again if restored/background tabs steal focus after the command returns; routine same-session commands skip focus correction, while observed pages without a returned native ID use `tab list` to establish current identity rather than inheriting an earlier tab's ID
|
|
198
208
|
- after successful tab creation, selection, or close, including dispatched native batch rows, read the now-active URL and fresh non-blank title—even when two tabs share a URL—before updating per-session page state; retain the deliberate blank target instead of treating it as accidental drift
|
|
199
|
-
- keep a per-session `refSnapshot` aligned with the last successful `snapshot` (including refs merged from a successful `batch` by taking the last successful `snapshot` step in batch result order): restore its once-stored ancestral definition when reloading, resuming, or moving to a different Pi session-tree branch, retain full membership and accessible metadata from that capture for wrapper-side diagnostics, drop it on successful close commands (`close`, `quit`, or `exit`), replace it with a persisted `page-transition` invalidation after any upstream-executed `record start` attempt (direct or batch; older supported natives can swap the page before their already-active check, so failed starts count; the warning and persisted summary explicitly describe conservative ref invalidation, not an observed page change), a `record restart` with a URL operand, `window new`, `diff url`, or WebMCP `invoke` / `result` / `cancel` (these page-provided tools can mutate, rerender, or navigate; when a spawned `batch` yields no parseable result rows, for example after a wrapper timeout, planned transition steps still record the invalidation), or after a failed transition command (`eval`, `back`, `forward`, `reload`, `connect`, `state load`, `tab` selection), including reached batch transitions and failed batch `open` rows whose live URL re-verification probe observed the page (a failed transition can still have mutated or replaced the document before throwing, so keeping the verified URL must not keep the prior refs; transcript replay preserves the persisted invalidation summary), and refuse page-scoped `@e…` argv before spawn when the active tab URL no longer matches the snapshot URL, when a ref id was never in that snapshot, when the snapshot state is invalidated, or when a `batch` step would reuse `@e…` on a guarded getter or mutation step after an earlier invalidating step (including `record start`, URL-bearing `record restart`, and WebMCP `invoke` / `result` / `cancel`) without a later `snapshot` step in the same plan;
|
|
209
|
+
- keep a per-session `refSnapshot` aligned with the last successful `snapshot` (including refs merged from a successful `batch` by taking the last successful `snapshot` step in batch result order): restore its once-stored ancestral definition when reloading, resuming, or moving to a different Pi session-tree branch, retain full membership and accessible metadata from that capture for wrapper-side diagnostics, drop it on successful close commands (`close`, `quit`, or `exit`), replace it with a persisted `page-transition` invalidation after any upstream-executed `record start` attempt (direct or batch; older supported natives can swap the page before their already-active check, so failed starts count; the warning and persisted summary explicitly describe conservative ref invalidation, not an observed page change), a `record restart` with a URL operand, `window new`, `diff url`, or WebMCP `invoke` / `result` / `cancel` (these page-provided tools can mutate, rerender, or navigate; when a spawned `batch` yields no parseable result rows, for example after a wrapper timeout, planned transition steps still record the invalidation), or after a failed transition command (`eval`, `back`, `forward`, `reload`, `connect`, `state load`, `tab` selection), including reached batch transitions and failed batch `open` rows whose live URL re-verification probe observed the page (a failed transition can still have mutated or replaced the document before throwing, so keeping the verified URL must not keep the prior refs; transcript replay preserves the persisted invalidation summary), and refuse page-scoped `@e…` argv before spawn when the active tab URL no longer matches the snapshot URL, when a ref id was never in that snapshot, when the snapshot state is invalidated, or when a `batch` step would reuse `@e…` on a guarded getter or mutation step after an earlier invalidating step (including `record start`, URL-bearing `record restart`, and WebMCP `invoke` / `result` / `cancel`) without a later `snapshot` step in the same plan; the latch scan covers the whole plan, including rows after its first snapshot even when no earlier refs exist, so a non-form click between snapshot and ref getter still requires another snapshot. Batch steps come from the source upstream actually executes (raw batch argument strings exclusively when any exist — filtering only the exact `--bail` token like upstream — stdin only otherwise, via `getUpstreamEffectiveBatchSteps` in `extensions/agent-browser/lib/orchestration/batch-stdin.ts`); tab recovery (which leaves user argv/stdin and continue-on-error control flow unchanged), artifact/recording preflight, batch screenshot path preparation (parent directories are created for effective raw rows too, without rewriting raw strings), and stale-ref echo args use that same selection so pinning and preflights cannot act on upstream-ignored stdin, while the pre-spawn state-policy validator deliberately keeps scanning parseable stdin alongside argv as a fail-closed content superset and treats stdin parse failures as fatal only when upstream would actually read stdin (its raw-token filter also uses the exact `--bail` token only). Same-snapshot `fill @e…` rows are guarded but do not themselves set that invalidation latch, so ordinary form fills can precede a click/submit row in one batch—see [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details) for the agent-visible contract and failure text; typed per-session tab/ref/pinning state lives in `extensions/agent-browser/lib/session-page-state.ts` and is updated by `orchestration/extension-observation.ts` after each tool result
|
|
200
210
|
- native 0.37 owns first-document setup inheritance for new tabs; the wrapper does not copy headers, user agents or other browser setup itself. The page-summary formatter displays native positive WebMCP availability while retaining raw details; it adds no discovery probe
|
|
201
211
|
- when a direct or batched WebMCP call returns `status: "pending"`, or `result` / `cancel` fails while that target is unknown, keep its tab target unknown and discard same-call snapshot evidence instead of treating an immediate post-dispatch URL probe as stable; `webmcp result` / `cancel`, `get url`, and explicit navigation remain available while unknown; replace the generic blocked snapshot action with `verify-page-target-after-pending-webmcp` (`get url`), and let a completed `batch --bail` use that verification before `snapshot -i` to re-establish both target and refs
|
|
202
212
|
- for top-level non-Electron direct `click` commands with an eligible target, install a bounded in-page target-specific event probe before upstream runs; if upstream reports success but no trusted pointer/mouse/click event reached the resolved target, fail the tool and report `details.clickDispatch` with explicit retry/inspect next actions (the wrapper does not replay clicks in-page). The probe covers `xpath=` targets and current `@e…` / `ref=` refs whose latest stored `refSnapshot.refs` role is `button`, `checkbox`, `menuitem`, `radio`, `switch`, or `tab`; it requires a unique role/name in the saved snapshot and the live candidates instead of taking a fresh pre-click snapshot that could recycle upstream refs. Ref and XPath candidates must additionally prove identity through a per-probe temporary DOM attribute read back by native `get attr <original-selector> <marker>`. Missing or mismatched identity, including XPath/frame scope mismatches, cleans up the probe and lets native click run without dispatch verification; candidate naming heuristics alone are never proof. Duplicate-name refs pass through without a probe: their old ordinal is not target identity. The probe is intentionally skipped when the effective native confirmation list guards `evaluate`, avoiding an optional-eval approval loop without bypassing native click policy. Dynamic action-policy files stay native-owned. It is also skipped for CSS selector clicks, unresolved `find … click` locators, and `batch`/`qa` click steps
|
|
203
213
|
- skip unrelated tools and harmless Bash inspections before building prompt policy. Seed the latest raw user message on start/tree, update it on user `message_end`, and re-read its current content before parsing policy so native content replacement cannot leave stale intent. Capture that policy at queued admission without a whole-branch scan on every event. Derive narrow prompt guards only for concrete evidence invariants: explicitly requested screenshot/recording output paths block browser close until the artifact manifest verifies those paths, while bare inbound attachment paths remain inputs. The wrapper intentionally does not infer broad business/user intent from prompt text such as order/payment/post boundaries; agents must follow those instructions themselves. The artifact guard is bounded preflight policy (`details.promptGuard`, `failureCategory: "policy-blocked"`), not a reusable browser recipe layer
|
|
204
|
-
- keep the existing page/selector scroll API;
|
|
214
|
+
- keep the existing page/selector scroll API; shims intercept only complete recognized shapes (`scroll to end|top` with exactly three tokens, or CSS-container scroll with three/four), passing surplus operands through to native execution without dropping them. Explicit CSS-container movement uses `Element.scrollBy` with `behavior: "instant"` before measuring offsets so smooth-scroll CSS cannot cause a premature no-movement failure
|
|
205
215
|
- reject direct and effective batch `scrollintoview text=...` / `scrollinto text=...` before dispatch because current upstream can falsely report success without movement, while leaving help forms untouched; return only native recovery (`find text ... hover` or fresh snapshot/ref), leaving CSS, XPath, and current-ref behavior upstream-owned
|
|
206
216
|
- after successful `get text` on a qualifying non-ref CSS selector, optionally issue one read-only `eval --stdin` probe per selector when multiple DOM matches or a hidden first match with visible peers could misread tabbed or off-screen content; simple id selectors and sensitive-looking literals skip this probe. Merge `details.selectorTextVisibility` / `selectorTextVisibilityAll`, visible warning lines, and `inspect-visible-text-candidates*` next actions as documented in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details) and `RQ-0074` in [`SUPPORT_MATRIX.md`](SUPPORT_MATRIX.md)
|
|
207
217
|
- caller-owned sessions honor native `AGENT_BROWSER_SOCKET_DIR` unless `PI_AGENT_BROWSER_SOCKET_DIR` overrides it, with the same socket integrity checks. For other local Unix launches, set a short private socket directory so extension-generated session names do not fail on the upstream Unix socket-path length limit; require the selected path to be absolute, owned by the current uid, mode `0700`, under checked ancestry, and free of symlink, foreign-owner, or special planted entries; reject pre-existing unsafe modes instead of repairing them, then recheck before spawn. The actual filesystem root `/` is supplied by the trusted operating environment: a directory without group/other write bits is accepted regardless of its reported owner, which can be unmapped in a Linux user namespace. Existing root-owned sticky-directory acceptance is unchanged. This boundary does not protect against whoever controls the root filesystem. Every non-root ancestor still needs trusted ownership and permissions, including the destination ancestry of root-owned aliases; a matching overflow UID is not trusted. Android/Termux uses `/data/data/<package>/piab`, treats the owner-only app-data directory as the trust anchor, permits the app's matching private uid/gid ancestry, compacts generated managed identities to one 80-bit digest so ordinary namespace plus fresh-session paths remain within the limit, and places policy-lock coordination under `os.tmpdir()` because Android `/tmp` is shell-owned and inaccessible
|
|
@@ -217,7 +227,7 @@ Native close/save and explicit URL reopen remain the persistence path, not a liv
|
|
|
217
227
|
|
|
218
228
|
### Launch flags
|
|
219
229
|
|
|
220
|
-
`native-session-defaults.ts` reads launch-argument/engine fields through its existing native-validated config discovery. Local Chrome composes `--no-startup-window` with
|
|
230
|
+
`native-session-defaults.ts` reads launch-argument/engine fields through its existing native-validated config discovery. Local Chrome composes `--no-startup-window` with caller CLI arguments only when native environment/config does not supply local launch defaults. Otherwise it leaves startup arguments entirely native-owned so browser, local auth, and helper calls do not alternate launch configurations. Callers wanting a single headed window with native launch defaults include `--no-startup-window` in their own `args`. Root bootstrap retains its existing helper scope; owned/fresh preparation reuses daemon-policy inspection, while explicit local callers use the same session-info probe. `process.ts` applies scoped arguments after managed restore-policy checks, composing the existing compatibility user agent without overriding caller Chrome arguments. Ordinary active calls do not receive new wrapper bootstrap settings. Native still owns CLI → environment → config precedence and hash-change restarts. This adds no browser launcher, profile mutation, tab cleanup, binary distribution, or persistent launch-settings state.
|
|
221
231
|
|
|
222
232
|
Input resolution replaces URL-less `open` with native `get url` before planning, retaining requested argv separately. Effective raw/stdin batch rows use the existing native argument parser and raw-over-stdin precedence; only changed rows are rewritten. Native URL reads provide lazy launch and real lifecycle/URL output without navigating an existing page. Explicit navigation and help/version input are unchanged.
|
|
223
233
|
|
|
@@ -252,6 +262,7 @@ When a managed implicit or fresh `--session` plan reaches process execution, `de
|
|
|
252
262
|
## Preferring the native tool
|
|
253
263
|
|
|
254
264
|
Keep the handling simple:
|
|
265
|
+
|
|
255
266
|
- prefer the native tool through extension guidance and tool-call guards
|
|
256
267
|
- do not rely on package skill overrides as the primary solution
|
|
257
268
|
|
|
@@ -268,7 +279,7 @@ Upstream restore-state persistence remains upstream-owned. The wrapper passes an
|
|
|
268
279
|
- clear missing-binary errors
|
|
269
280
|
- filtered `network requests --current-page` / `--current-origin` / `--current-url` preparation results use the same `redactPresentationData` credential redactor as ordinary diagnostics before populating `details.data` or writing `outputPath`
|
|
270
281
|
- compact result summaries, including presentation-time redaction: stateful browser-context commands (`auth`, `cookies`, `storage`, `dialog`, `frame`, `state`) use field-aware value redaction and compact formatters, while other structured upstream JSON (for example `network`, `diff`, `trace` / `profiler` / `record`, `console` / `errors` / `highlight` / `inspect` / `clipboard`, `stream`, `dashboard`, and `chat`) is passed through `redactPresentationData` in `extensions/agent-browser/lib/results/presentation.ts` so model-facing `details.data` and batch roll-ups stay compact and do not echo bearer tokens, proxy passwords, or similar fields verbatim; `redactInvocationArgs` in `extensions/agent-browser/lib/runtime.ts` masks trailing values for sensitive global flags such as `--body`, `--headers`, `--password`, and `--proxy`, preserves positional rules for `cookies set` and `storage local|session set` while distinguishing native `--curl` file-import operands from inline cookie values (including failed batch diagnostics), and nested `batch` steps use the same argv and error-body scrubbing before echoing commands or errors. Shared URL redaction covers SAMLRequest/SAMLResponse/RelayState and auth-context-only state/nonce at model/persisted-artifact boundaries while retaining exact internal page-target URLs; snapshot spills are redacted before disk writes
|
|
271
|
-
- bounded machine-readable outcome metadata on tool `details` (`resultCategory`, `successCategory`, `failureCategory`, optional `nextActions`, optional `pageChangeSummary` with observed-vs-dispatched evidence and per-step summaries on `batch`, optional `artifactVerification` with the same shape on each successful `batchSteps[]` row) so agents can branch without parsing prose; enums, classifier precedence, and generic follow-up payloads are implemented under `extensions/agent-browser/lib/results/` in focused modules (`contracts.ts` for shared types, `categories.ts` for `classifyAgentBrowserSuccessCategory` / `classifyAgentBrowserFailureCategory` / `buildAgentBrowserResultCategoryDetails`, `action-recommendations.ts` for `buildAgentBrowserNextActions`, `
|
|
282
|
+
- bounded machine-readable outcome metadata on tool `details` (`resultCategory`, `successCategory`, `failureCategory`, optional `nextActions`, optional `pageChangeSummary` with observed-vs-dispatched evidence and per-step summaries on `batch`, optional `artifactVerification` with the same shape on each successful `batchSteps[]` row) so agents can branch without parsing prose; enums, classifier precedence, and generic follow-up payloads are implemented under `extensions/agent-browser/lib/results/` in focused modules (`contracts.ts` for shared types, `categories.ts` for `classifyAgentBrowserSuccessCategory` / `classifyAgentBrowserFailureCategory` / `buildAgentBrowserResultCategoryDetails`, `action-recommendations.ts` for `buildAgentBrowserNextActions`, `action-contracts.ts` for the `AgentBrowserNextAction` shape and `next-actions.ts` for merge helpers, `recovery-actions.ts` for recovery id registries and `buildRecoveryNextActions`, `network.ts` for `classifyNetworkRequestFailure` / `summarizeNetworkFailures`, and related helpers). Per-session tab target, `refSnapshot` alignment, invalidation, and tab pinning observations flow through `extensions/agent-browser/lib/session-page-state.ts` through `orchestration/extension-observation.ts` and branch restore. Compact page-change summaries and artifact verification rollups are built in `results/presentation/navigation.ts` and `artifact-verification.ts` (`buildPageChangeSummary`, `buildArtifactVerificationSummary`), and the human contract lives in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details). Final public results return native `isError` after all wrapper reclassifications, without a `tool_result` repair hook. Prose retains the visible category notice; explicit parseable JSON stays unchanged. `lib/native-output.ts` and `finalizeAgentBrowserFailure` in `lib/pi-tool-rendering.ts` keep structured observations, transcript status and TUI affordances aligned (transcript semantics in the same contract doc)
|
|
272
283
|
- inline screenshots/images for the plain `screenshot` command; other image-like saves (for example `diff screenshot`) still appear in `details.artifacts` and summaries but are not auto-inlined as Pi image attachments (see [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details))
|
|
273
284
|
- lightweight session convenience
|
|
274
285
|
- docs, including a repo-readable command reference that mirrors the blocked direct-binary help path closely enough for normal agent work
|
|
@@ -296,6 +307,7 @@ This mirrors the playbook contract pattern described in [`TOOL_CONTRACT.md`](TOO
|
|
|
296
307
|
## Not the right design
|
|
297
308
|
|
|
298
309
|
Avoid:
|
|
310
|
+
|
|
299
311
|
- duplicating native CLI semantics in bespoke tools
|
|
300
312
|
- compatibility layers for old `agent-browser` versions
|
|
301
313
|
- deep embedded SDK-style integration
|
|
@@ -322,6 +334,7 @@ Avoid:
|
|
|
322
334
|
## Summary
|
|
323
335
|
|
|
324
336
|
The architecture should stay:
|
|
337
|
+
|
|
325
338
|
- thin
|
|
326
339
|
- aligned to the recommended upstream release and stable support floor
|
|
327
340
|
- close to upstream
|