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,568 +1,138 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isRecord } from "./parsing.js";
|
|
3
|
-
import { AGENT_BROWSER_NAMESPACE, AGENT_BROWSER_OUTPUT_SCHEMA, finalizeAgentBrowserNativeResult } from "./native-output.js";
|
|
1
|
+
import { AGENT_BROWSER_NAMESPACE, AGENT_BROWSER_OUTPUT_SCHEMA, finalizeAgentBrowserNativeResult, } from "./native-output.js";
|
|
4
2
|
import { redactSensitiveText } from "./runtime.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { isRecord } from "./parsing.js";
|
|
4
|
+
import { isStringArray } from "./results/presentation/content.js";
|
|
5
|
+
import { redactPresentationData } from "./results/presentation/diagnostic-redaction.js";
|
|
6
|
+
import { isWebSearchProvider, resolvePreferredWebSearchCredential, } from "./config.js";
|
|
7
|
+
import { AgentBrowserWebSearchParams, DEFAULT_SEARCH_RESULT_COUNT, MAX_SEARCH_RESULT_COUNT, } from "./web-search-schema.js";
|
|
8
|
+
import { WebSearchRequestGate } from "./web-search-request.js";
|
|
9
|
+
import { WebSearchLocalError, prepareWebSearchRequest } from "./web-search-providers.js";
|
|
10
|
+
import { dedupeSearchResults, formatSearchResults, } from "./web-search-results.js";
|
|
11
|
+
export { EXA_SEARCH_TYPES } from "./config.js";
|
|
12
|
+
export { AgentBrowserWebSearchParams, createAgentBrowserWebSearchParamsSchema, } from "./web-search-schema.js";
|
|
13
|
+
export { WEB_SEARCH_MIN_REQUEST_INTERVAL_MS, WebSearchRequestGate } from "./web-search-request.js";
|
|
14
|
+
export { EXA_SEARCH_SYSTEM_PROMPT, buildBraveSearchUrl, buildExaSearchRequestBody, fetchBraveSearchJson, fetchExaSearchJson, } from "./web-search-providers.js";
|
|
15
|
+
export { cleanSearchText, decodeHtmlEntities, normalizeBraveSearchResult, normalizeExaSearchResult, } from "./web-search-results.js";
|
|
7
16
|
export const AGENT_BROWSER_WEB_SEARCH_TOOL_NAME = "agent_browser_web_search";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const MAX_SEARCH_RESULT_COUNT = 10;
|
|
12
|
-
const SEARCH_REQUEST_TIMEOUT_MS = 15_000;
|
|
13
|
-
const EXA_DEEP_LITE_SEARCH_REQUEST_TIMEOUT_MS = 45_000;
|
|
14
|
-
const EXA_DEEP_SEARCH_REQUEST_TIMEOUT_MS = 60_000;
|
|
15
|
-
const EXA_DEEP_REASONING_SEARCH_REQUEST_TIMEOUT_MS = 90_000;
|
|
16
|
-
const EXA_DYNAMIC_HIGHLIGHTS_BETA = "dynamic-highlights-2026-08-28";
|
|
17
|
-
export const WEB_SEARCH_MIN_REQUEST_INTERVAL_MS = 1_100;
|
|
18
|
-
export const EXA_SEARCH_SYSTEM_PROMPT = "Prefer primary, official sources. Respect any requested version or date. Avoid duplicate or equivalent results.";
|
|
19
|
-
export { EXA_SEARCH_TYPES };
|
|
20
|
-
const WEB_SEARCH_PROVIDER_PARAM_VALUES = ["auto", ...WEB_SEARCH_PROVIDERS];
|
|
21
|
-
const EXA_SEARCH_CATEGORIES = ["company", "people", "publication", "news", "personal site", "financial report"];
|
|
22
|
-
const MAX_EXA_DOMAIN_FILTERS = 20;
|
|
23
|
-
const MAX_EXA_ADDITIONAL_QUERIES = 10;
|
|
24
|
-
export function createAgentBrowserWebSearchParamsSchema(Type = JsonSchema, StringEnum = localStringEnum) {
|
|
25
|
-
return Type.Object({
|
|
26
|
-
query: Type.String({
|
|
27
|
-
minLength: 1,
|
|
28
|
-
description: "Search query to run with the configured Exa or Brave web search provider.",
|
|
29
|
-
}),
|
|
30
|
-
provider: Type.Optional(StringEnum(WEB_SEARCH_PROVIDER_PARAM_VALUES, {
|
|
31
|
-
description: `Optional provider override. auto uses configured keys and preferredProvider; when both Exa and Brave are available, the default preferred provider is ${DEFAULT_WEB_SEARCH_PROVIDER}.`,
|
|
32
|
-
})),
|
|
33
|
-
searchType: Type.Optional(StringEnum(EXA_SEARCH_TYPES, {
|
|
34
|
-
description: "Exa mode; omitted uses webSearch.defaultSearchType, then auto. instant (~250ms) is only for trivial lookups; fast (~450ms) favors latency; auto (~1s) is balanced. Pass searchType: deep-lite (~4s) for research before implementation unless config already defaults it; do not assume auto is deep enough. deep (4–15s) handles hard multi-source research; deep-reasoning (12–40s) is only for the hardest work. Brave ignores this field.",
|
|
35
|
-
})),
|
|
36
|
-
includeDomains: Type.Optional(Type.Array(Type.String({ minLength: 1 }), {
|
|
37
|
-
minItems: 1,
|
|
38
|
-
maxItems: MAX_EXA_DOMAIN_FILTERS,
|
|
39
|
-
description: `Exa only. Limit results to 1–${MAX_EXA_DOMAIN_FILTERS} hostnames, path prefixes (exa.ai/docs), or wildcard subdomains (*.substack.com).`,
|
|
40
|
-
})),
|
|
41
|
-
excludeDomains: Type.Optional(Type.Array(Type.String({ minLength: 1 }), {
|
|
42
|
-
minItems: 1,
|
|
43
|
-
maxItems: MAX_EXA_DOMAIN_FILTERS,
|
|
44
|
-
description: `Exa only. Exclude 1–${MAX_EXA_DOMAIN_FILTERS} hostnames, path prefixes, or wildcard subdomains. Not compatible with category company or people.`,
|
|
45
|
-
})),
|
|
46
|
-
category: Type.Optional(StringEnum(EXA_SEARCH_CATEGORIES, {
|
|
47
|
-
description: "Exa-only result category. company and people cannot be combined with freshness or excludeDomains.",
|
|
48
|
-
})),
|
|
49
|
-
additionalQueries: Type.Optional(Type.Array(Type.String({ minLength: 1 }), {
|
|
50
|
-
minItems: 1,
|
|
51
|
-
maxItems: MAX_EXA_ADDITIONAL_QUERIES,
|
|
52
|
-
description: `Exa only. Add 1–${MAX_EXA_ADDITIONAL_QUERIES} query variations when the effective searchType is deep-lite, deep, or deep-reasoning.`,
|
|
53
|
-
})),
|
|
54
|
-
highlightsDynamic: Type.Optional(Type.Boolean({
|
|
55
|
-
description: "Exa-only research preview. Allocate one highlight budget across all results; the wrapper sends the required Exa-Beta header. Regular per-page highlights remain the default.",
|
|
56
|
-
})),
|
|
57
|
-
count: Type.Optional(Type.Integer({
|
|
58
|
-
minimum: 1,
|
|
59
|
-
maximum: MAX_SEARCH_RESULT_COUNT,
|
|
60
|
-
description: `Number of web results to return. Defaults to ${DEFAULT_SEARCH_RESULT_COUNT}; max ${MAX_SEARCH_RESULT_COUNT}.`,
|
|
61
|
-
})),
|
|
62
|
-
offset: Type.Optional(Type.Integer({
|
|
63
|
-
minimum: 0,
|
|
64
|
-
maximum: 9,
|
|
65
|
-
description: "Zero-based result offset for pagination. Defaults to 0.",
|
|
66
|
-
})),
|
|
67
|
-
country: Type.Optional(Type.String({
|
|
68
|
-
pattern: "^[A-Za-z]{2}$",
|
|
69
|
-
description: "Optional 2-letter country code, such as US or GB.",
|
|
70
|
-
})),
|
|
71
|
-
searchLang: Type.Optional(Type.String({
|
|
72
|
-
minLength: 2,
|
|
73
|
-
maxLength: 8,
|
|
74
|
-
description: "Optional Brave search language code, such as en or en-US.",
|
|
75
|
-
})),
|
|
76
|
-
safesearch: Type.Optional(StringEnum(["off", "moderate", "strict"], {
|
|
77
|
-
description: "Optional search safety setting. Brave forwards this as safesearch; Exa maps moderate/strict to moderation=true.",
|
|
78
|
-
})),
|
|
79
|
-
freshness: Type.Optional(StringEnum(["pd", "pw", "pm", "py"], {
|
|
80
|
-
description: "Optional freshness window: pd=past day, pw=past week, pm=past month, py=past year.",
|
|
81
|
-
})),
|
|
82
|
-
}, { additionalProperties: false });
|
|
83
|
-
}
|
|
84
|
-
export const AgentBrowserWebSearchParams = createAgentBrowserWebSearchParamsSchema();
|
|
85
|
-
const HTML_ENTITY_REPLACEMENTS = {
|
|
86
|
-
amp: "&",
|
|
87
|
-
apos: "'",
|
|
88
|
-
gt: ">",
|
|
89
|
-
lt: "<",
|
|
90
|
-
nbsp: " ",
|
|
91
|
-
quot: '"',
|
|
92
|
-
};
|
|
93
|
-
const HTML_TAG_NAMES_TO_STRIP = new Set([
|
|
94
|
-
"a",
|
|
95
|
-
"abbr",
|
|
96
|
-
"address",
|
|
97
|
-
"article",
|
|
98
|
-
"aside",
|
|
99
|
-
"audio",
|
|
100
|
-
"b",
|
|
101
|
-
"base",
|
|
102
|
-
"blockquote",
|
|
103
|
-
"body",
|
|
104
|
-
"br",
|
|
105
|
-
"button",
|
|
106
|
-
"canvas",
|
|
107
|
-
"code",
|
|
108
|
-
"div",
|
|
109
|
-
"em",
|
|
110
|
-
"embed",
|
|
111
|
-
"footer",
|
|
112
|
-
"form",
|
|
113
|
-
"h1",
|
|
114
|
-
"h2",
|
|
115
|
-
"h3",
|
|
116
|
-
"h4",
|
|
117
|
-
"h5",
|
|
118
|
-
"h6",
|
|
119
|
-
"head",
|
|
120
|
-
"header",
|
|
121
|
-
"html",
|
|
122
|
-
"i",
|
|
123
|
-
"iframe",
|
|
124
|
-
"img",
|
|
125
|
-
"input",
|
|
126
|
-
"li",
|
|
127
|
-
"link",
|
|
128
|
-
"main",
|
|
129
|
-
"mark",
|
|
130
|
-
"math",
|
|
131
|
-
"meta",
|
|
132
|
-
"nav",
|
|
133
|
-
"object",
|
|
134
|
-
"ol",
|
|
135
|
-
"option",
|
|
136
|
-
"p",
|
|
137
|
-
"pre",
|
|
138
|
-
"script",
|
|
139
|
-
"section",
|
|
140
|
-
"select",
|
|
141
|
-
"source",
|
|
142
|
-
"span",
|
|
143
|
-
"strong",
|
|
144
|
-
"style",
|
|
145
|
-
"svg",
|
|
146
|
-
"table",
|
|
147
|
-
"tbody",
|
|
148
|
-
"td",
|
|
149
|
-
"textarea",
|
|
150
|
-
"tfoot",
|
|
151
|
-
"th",
|
|
152
|
-
"thead",
|
|
153
|
-
"tr",
|
|
154
|
-
"u",
|
|
155
|
-
"ul",
|
|
156
|
-
"video",
|
|
157
|
-
]);
|
|
158
|
-
function decodeHtmlEntity(entity) {
|
|
159
|
-
const named = HTML_ENTITY_REPLACEMENTS[entity.toLowerCase()];
|
|
160
|
-
if (named !== undefined)
|
|
161
|
-
return named;
|
|
162
|
-
const decimalMatch = /^#(\d+)$/.exec(entity);
|
|
163
|
-
const hexMatch = /^#x([0-9a-f]+)$/i.exec(entity);
|
|
164
|
-
const codePoint = decimalMatch ? Number.parseInt(decimalMatch[1] ?? "", 10) : hexMatch ? Number.parseInt(hexMatch[1] ?? "", 16) : undefined;
|
|
165
|
-
if (codePoint === undefined || !Number.isFinite(codePoint))
|
|
166
|
-
return `&${entity};`;
|
|
167
|
-
try {
|
|
168
|
-
return String.fromCodePoint(codePoint);
|
|
17
|
+
function buildMissingCredentialError(provider) {
|
|
18
|
+
if (provider === "brave") {
|
|
19
|
+
return "agent_browser_web_search provider brave was requested but no BRAVE_API_KEY/config credential resolved.";
|
|
169
20
|
}
|
|
170
|
-
|
|
171
|
-
return
|
|
21
|
+
if (provider === "exa") {
|
|
22
|
+
return "agent_browser_web_search provider exa was requested but no EXA_API_KEY/config credential resolved.";
|
|
172
23
|
}
|
|
24
|
+
return "No Exa or Brave web search credential resolved. Configure webSearch.exaApiKey or webSearch.braveApiKey, or load EXA_API_KEY/BRAVE_API_KEY in the runtime environment.";
|
|
173
25
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
function stripDecodedHtmlTags(value) {
|
|
178
|
-
return value.replace(/<(script|style)\b[^>]*>[\s\S]*?<\/\1>/gi, " ").replace(/<\/?([a-z][a-z0-9-]*)(\s[^>]*)?>/gi, (match, tagName, attributes) => {
|
|
179
|
-
if (attributes || match.startsWith("</") || HTML_TAG_NAMES_TO_STRIP.has(tagName.toLowerCase()))
|
|
180
|
-
return " ";
|
|
181
|
-
return match;
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
export function cleanSearchText(value, maxLength = 500) {
|
|
185
|
-
if (typeof value !== "string")
|
|
186
|
-
return undefined;
|
|
187
|
-
const cleaned = stripDecodedHtmlTags(decodeHtmlEntities(value.replace(/<[^>]*>/g, " ")))
|
|
188
|
-
.replace(/\s+/g, " ")
|
|
189
|
-
.trim();
|
|
190
|
-
if (!cleaned)
|
|
191
|
-
return undefined;
|
|
192
|
-
if (cleaned.length <= maxLength)
|
|
193
|
-
return cleaned;
|
|
194
|
-
return `${cleaned.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
|
|
195
|
-
}
|
|
196
|
-
function normalizeSearchUrl(value) {
|
|
197
|
-
if (typeof value !== "string")
|
|
198
|
-
return undefined;
|
|
199
|
-
try {
|
|
200
|
-
const url = new URL(value);
|
|
201
|
-
if (url.protocol !== "http:" && url.protocol !== "https:")
|
|
202
|
-
return undefined;
|
|
203
|
-
return url.toString();
|
|
26
|
+
function validateRuntimeConfig(state) {
|
|
27
|
+
if (state.errors.length > 0) {
|
|
28
|
+
throw new WebSearchLocalError(`agent_browser_web_search config is invalid: ${state.errors.join("; ")}`);
|
|
204
29
|
}
|
|
205
|
-
|
|
206
|
-
|
|
30
|
+
if (!state.webSearchEnabled) {
|
|
31
|
+
throw new WebSearchLocalError("agent_browser_web_search is disabled by pi-agent-browser-native config.");
|
|
207
32
|
}
|
|
208
33
|
}
|
|
209
|
-
function
|
|
210
|
-
|
|
211
|
-
return
|
|
34
|
+
function validateProviderParams(provider, params) {
|
|
35
|
+
if (provider !== "brave") {
|
|
36
|
+
return;
|
|
212
37
|
}
|
|
213
|
-
|
|
214
|
-
|
|
38
|
+
const exaOnlyFields = [
|
|
39
|
+
params.includeDomains ? "includeDomains" : undefined,
|
|
40
|
+
params.excludeDomains ? "excludeDomains" : undefined,
|
|
41
|
+
params.category !== undefined ? "category" : undefined,
|
|
42
|
+
params.additionalQueries ? "additionalQueries" : undefined,
|
|
43
|
+
params.highlightsDynamic === true ? "highlightsDynamic" : undefined,
|
|
44
|
+
].filter((field) => field !== undefined);
|
|
45
|
+
if (exaOnlyFields.length > 0) {
|
|
46
|
+
throw new WebSearchLocalError(`${exaOnlyFields.join(", ")} ${exaOnlyFields.length === 1 ? "requires" : "require"} provider exa; resolved provider was brave.`);
|
|
215
47
|
}
|
|
216
48
|
}
|
|
217
|
-
function
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
.slice(0, 3);
|
|
224
|
-
return highlights.length > 0 ? highlights : undefined;
|
|
225
|
-
}
|
|
226
|
-
export function normalizeBraveSearchResult(result) {
|
|
227
|
-
const title = cleanSearchText(result.title, 180);
|
|
228
|
-
const url = normalizeSearchUrl(result.url);
|
|
229
|
-
if (!title || !url)
|
|
230
|
-
return undefined;
|
|
231
|
-
const pageDate = cleanSearchText(result.page_age, 80);
|
|
232
|
-
return {
|
|
233
|
-
title,
|
|
234
|
-
url,
|
|
235
|
-
description: cleanSearchText(result.description, 320),
|
|
236
|
-
source: cleanSearchText(result.profile?.name, 120) ?? cleanSearchText(result.meta_url?.hostname, 120),
|
|
237
|
-
age: cleanSearchText(result.age, 80),
|
|
238
|
-
...(pageDate ? { pageDate } : {}),
|
|
239
|
-
language: cleanSearchText(result.language, 40),
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
export function normalizeExaSearchResult(result) {
|
|
243
|
-
const title = cleanSearchText(result.title, 180);
|
|
244
|
-
const url = normalizeSearchUrl(result.url);
|
|
245
|
-
if (!title || !url)
|
|
246
|
-
return undefined;
|
|
247
|
-
const highlights = normalizeHighlightList(result.highlights);
|
|
248
|
-
const pageDate = cleanSearchText(result.publishedDate, 80);
|
|
249
|
-
return {
|
|
250
|
-
title,
|
|
251
|
-
url,
|
|
252
|
-
description: cleanSearchText(result.summary, 320) ?? highlights?.[0] ?? cleanSearchText(result.text, 320),
|
|
253
|
-
highlights,
|
|
254
|
-
source: cleanSearchText(result.author, 120) ?? cleanSearchText(getHostname(url), 120),
|
|
255
|
-
...(pageDate ? { pageDate } : {}),
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
function getProviderLabel(provider) {
|
|
259
|
-
return provider === "exa" ? "Exa" : "Brave";
|
|
260
|
-
}
|
|
261
|
-
function formatSearchResults(provider, query, results) {
|
|
262
|
-
const providerLabel = getProviderLabel(provider);
|
|
263
|
-
if (results.length === 0) {
|
|
264
|
-
return `No ${providerLabel} web results found for: ${query}`;
|
|
265
|
-
}
|
|
266
|
-
const lines = [`${providerLabel} web search results for: ${query}`, ""];
|
|
267
|
-
results.forEach((result, index) => {
|
|
268
|
-
lines.push(`${index + 1}. ${result.title}`);
|
|
269
|
-
lines.push(` URL: ${result.url}`);
|
|
270
|
-
if (result.source)
|
|
271
|
-
lines.push(` Source: ${result.source}`);
|
|
272
|
-
if (result.pageDate)
|
|
273
|
-
lines.push(` ${provider === "exa" ? "Published" : "Page date"}: ${result.pageDate}`);
|
|
274
|
-
if (result.age)
|
|
275
|
-
lines.push(` Age: ${result.age}`);
|
|
276
|
-
if (result.description)
|
|
277
|
-
lines.push(` Summary: ${result.description}`);
|
|
278
|
-
if (result.highlights && result.highlights.length > 1) {
|
|
279
|
-
lines.push(" Highlights:");
|
|
280
|
-
for (const highlight of result.highlights)
|
|
281
|
-
lines.push(` - ${highlight}`);
|
|
282
|
-
}
|
|
283
|
-
lines.push("");
|
|
49
|
+
async function runWebSearch(state, params, gate, signal) {
|
|
50
|
+
validateRuntimeConfig(state);
|
|
51
|
+
const requestedProvider = params.provider ?? "auto";
|
|
52
|
+
const resolved = await resolvePreferredWebSearchCredential(state, {
|
|
53
|
+
provider: requestedProvider,
|
|
54
|
+
signal,
|
|
284
55
|
});
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
export function buildBraveSearchUrl(params) {
|
|
288
|
-
const url = new URL(BRAVE_SEARCH_ENDPOINT);
|
|
289
|
-
url.searchParams.set("q", params.query);
|
|
290
|
-
url.searchParams.set("count", String(params.count));
|
|
291
|
-
url.searchParams.set("offset", String(params.offset));
|
|
292
|
-
if (params.country)
|
|
293
|
-
url.searchParams.set("country", params.country.toUpperCase());
|
|
294
|
-
if (params.searchLang)
|
|
295
|
-
url.searchParams.set("search_lang", params.searchLang);
|
|
296
|
-
if (params.safesearch)
|
|
297
|
-
url.searchParams.set("safesearch", params.safesearch);
|
|
298
|
-
if (params.freshness)
|
|
299
|
-
url.searchParams.set("freshness", params.freshness);
|
|
300
|
-
return url;
|
|
301
|
-
}
|
|
302
|
-
const FRESHNESS_DAYS = {
|
|
303
|
-
pd: 1,
|
|
304
|
-
pw: 7,
|
|
305
|
-
pm: 31,
|
|
306
|
-
py: 365,
|
|
307
|
-
};
|
|
308
|
-
function getStartPublishedDate(freshness, now) {
|
|
309
|
-
if (!freshness)
|
|
310
|
-
return undefined;
|
|
311
|
-
const days = FRESHNESS_DAYS[freshness];
|
|
312
|
-
return new Date(now().getTime() - days * 24 * 60 * 60 * 1000).toISOString();
|
|
313
|
-
}
|
|
314
|
-
export function buildExaSearchRequestBody(params, now = () => new Date()) {
|
|
315
|
-
const searchType = params.searchType ?? "auto";
|
|
316
|
-
if (params.additionalQueries?.length && !searchType.startsWith("deep")) {
|
|
317
|
-
throw new WebSearchLocalError(`additionalQueries requires deep-lite, deep, or deep-reasoning; received ${searchType}.`);
|
|
56
|
+
if (!resolved) {
|
|
57
|
+
throw new WebSearchLocalError(buildMissingCredentialError(requestedProvider));
|
|
318
58
|
}
|
|
319
|
-
|
|
320
|
-
|
|
59
|
+
validateProviderParams(resolved.provider, params);
|
|
60
|
+
const query = params.query.trim();
|
|
61
|
+
if (query.length === 0) {
|
|
62
|
+
throw new WebSearchLocalError("query must not be blank");
|
|
321
63
|
}
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
64
|
+
const count = Math.min(Math.max(params.count ?? DEFAULT_SEARCH_RESULT_COUNT, 1), MAX_SEARCH_RESULT_COUNT);
|
|
65
|
+
const offset = Math.max(params.offset ?? 0, 0);
|
|
66
|
+
const executionParams = {
|
|
67
|
+
additionalQueries: params.additionalQueries,
|
|
68
|
+
category: params.category,
|
|
69
|
+
country: params.country,
|
|
70
|
+
count,
|
|
71
|
+
excludeDomains: params.excludeDomains,
|
|
72
|
+
freshness: params.freshness,
|
|
73
|
+
highlightsDynamic: params.highlightsDynamic,
|
|
74
|
+
includeDomains: params.includeDomains,
|
|
75
|
+
offset,
|
|
76
|
+
query,
|
|
77
|
+
safesearch: params.safesearch,
|
|
78
|
+
searchLang: params.searchLang,
|
|
79
|
+
searchType: params.searchType ?? state.config.webSearch?.defaultSearchType ?? "auto",
|
|
80
|
+
};
|
|
81
|
+
const request = prepareWebSearchRequest(resolved.provider, executionParams, resolved.credential.value, signal);
|
|
82
|
+
const normalized = await gate.run(signal, request);
|
|
83
|
+
const results = dedupeSearchResults(normalized.results);
|
|
84
|
+
const duplicatesRemoved = normalized.results.length - results.length;
|
|
85
|
+
return {
|
|
86
|
+
provider: resolved.provider,
|
|
87
|
+
query,
|
|
88
|
+
returnedQuery: normalized.returnedQuery,
|
|
89
|
+
count,
|
|
90
|
+
offset,
|
|
91
|
+
...normalized.extraDetails,
|
|
92
|
+
fetchedAt: new Date().toISOString(),
|
|
93
|
+
results,
|
|
94
|
+
duplicatesRemoved: duplicatesRemoved > 0 ? duplicatesRemoved : undefined,
|
|
328
95
|
};
|
|
329
|
-
if (params.category)
|
|
330
|
-
body.category = params.category;
|
|
331
|
-
if (params.country)
|
|
332
|
-
body.userLocation = params.country.toUpperCase();
|
|
333
|
-
if (params.includeDomains?.length)
|
|
334
|
-
body.includeDomains = params.includeDomains;
|
|
335
|
-
if (params.excludeDomains?.length)
|
|
336
|
-
body.excludeDomains = params.excludeDomains;
|
|
337
|
-
if (params.additionalQueries?.length)
|
|
338
|
-
body.additionalQueries = params.additionalQueries;
|
|
339
|
-
if (params.safesearch && params.safesearch !== "off")
|
|
340
|
-
body.moderation = true;
|
|
341
|
-
const startPublishedDate = getStartPublishedDate(params.freshness, now);
|
|
342
|
-
if (startPublishedDate)
|
|
343
|
-
body.startPublishedDate = startPublishedDate;
|
|
344
|
-
return body;
|
|
345
|
-
}
|
|
346
|
-
function redactSearchSecret(text, apiKey) {
|
|
347
|
-
return apiKey ? text.split(apiKey).join("[REDACTED]") : text;
|
|
348
|
-
}
|
|
349
|
-
function sleepWithAbort(ms, signal) {
|
|
350
|
-
if (ms <= 0)
|
|
351
|
-
return Promise.resolve();
|
|
352
|
-
if (signal?.aborted)
|
|
353
|
-
return Promise.reject(signal.reason ?? new Error("Web search cancelled"));
|
|
354
|
-
return new Promise((resolve, reject) => {
|
|
355
|
-
const cleanup = () => signal?.removeEventListener("abort", abort);
|
|
356
|
-
const timeout = setTimeout(() => {
|
|
357
|
-
cleanup();
|
|
358
|
-
resolve();
|
|
359
|
-
}, ms);
|
|
360
|
-
const abort = () => {
|
|
361
|
-
clearTimeout(timeout);
|
|
362
|
-
cleanup();
|
|
363
|
-
reject(signal?.reason ?? new Error("Web search cancelled"));
|
|
364
|
-
};
|
|
365
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
export class WebSearchRequestGate {
|
|
369
|
-
now;
|
|
370
|
-
sleep;
|
|
371
|
-
lastRequestStartedAt = 0;
|
|
372
|
-
tail = Promise.resolve();
|
|
373
|
-
constructor(now = Date.now, sleep = sleepWithAbort) {
|
|
374
|
-
this.now = now;
|
|
375
|
-
this.sleep = sleep;
|
|
376
|
-
}
|
|
377
|
-
run(signal, task) {
|
|
378
|
-
const runTask = async () => {
|
|
379
|
-
const elapsedMs = this.lastRequestStartedAt === 0 ? WEB_SEARCH_MIN_REQUEST_INTERVAL_MS : this.now() - this.lastRequestStartedAt;
|
|
380
|
-
const waitMs = Math.max(0, WEB_SEARCH_MIN_REQUEST_INTERVAL_MS - elapsedMs);
|
|
381
|
-
if (waitMs > 0)
|
|
382
|
-
await this.sleep(waitMs, signal);
|
|
383
|
-
if (signal?.aborted)
|
|
384
|
-
throw signal.reason ?? new Error("Web search cancelled");
|
|
385
|
-
this.lastRequestStartedAt = this.now();
|
|
386
|
-
return task();
|
|
387
|
-
};
|
|
388
|
-
const result = this.tail.then(runTask, runTask);
|
|
389
|
-
this.tail = result.catch(() => undefined);
|
|
390
|
-
return result;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
function formatSearchHttpError(provider, status, statusText, body, apiKey) {
|
|
394
|
-
const providerLabel = getProviderLabel(provider);
|
|
395
|
-
const errorPreview = cleanSearchText(redactSearchSecret(body, apiKey), 300);
|
|
396
|
-
if (status === 429) {
|
|
397
|
-
const preview = errorPreview ? ` Upstream details: ${redactSearchSecret(errorPreview, apiKey)}` : "";
|
|
398
|
-
return `${providerLabel} search rate limit exceeded (HTTP 429). Do not issue parallel or repeated agent_browser_web_search calls; use one high-signal query, inspect those results, then wait before retrying or ask the user to adjust their ${providerLabel} API plan/limits.${preview}`;
|
|
399
|
-
}
|
|
400
|
-
return `${providerLabel} search failed with HTTP ${status}: ${errorPreview ? redactSearchSecret(errorPreview, apiKey) : statusText}`;
|
|
401
96
|
}
|
|
402
|
-
async function
|
|
403
|
-
|
|
404
|
-
|
|
97
|
+
async function presentSearchSuccess(rawDetails, params) {
|
|
98
|
+
const details = redactPresentationData({ command: "web-search" }, rawDetails);
|
|
99
|
+
if (!isRecord(details) ||
|
|
100
|
+
!isWebSearchProvider(details.provider) ||
|
|
101
|
+
typeof details.returnedQuery !== "string" ||
|
|
102
|
+
!Array.isArray(details.results) ||
|
|
103
|
+
!details.results.every(isNormalizedSearchResult)) {
|
|
104
|
+
throw new Error("Web search presentation has invalid result structure.");
|
|
405
105
|
}
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
});
|
|
415
|
-
const text = await response.text();
|
|
416
|
-
if (!response.ok) {
|
|
417
|
-
throw new Error(formatSearchHttpError(options.provider, response.status, response.statusText, text, options.apiKey));
|
|
418
|
-
}
|
|
419
|
-
try {
|
|
420
|
-
return JSON.parse(text);
|
|
421
|
-
}
|
|
422
|
-
catch (error) {
|
|
423
|
-
throw new Error(`${options.invalidJsonMessage}: ${error instanceof Error ? error.message : String(error)}`);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
finally {
|
|
427
|
-
clearTimeout(timeout);
|
|
428
|
-
options.signal?.removeEventListener("abort", abort);
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
export async function fetchBraveSearchJson(url, apiKey, signal) {
|
|
432
|
-
return fetchSearchJson({
|
|
433
|
-
apiKey,
|
|
434
|
-
cancelMessage: "Brave search cancelled",
|
|
435
|
-
init: {
|
|
436
|
-
headers: {
|
|
437
|
-
Accept: "application/json",
|
|
438
|
-
"X-Subscription-Token": apiKey,
|
|
106
|
+
const duplicateNotice = typeof details.duplicatesRemoved === "number"
|
|
107
|
+
? `\n\nDuplicate URLs removed: ${details.duplicatesRemoved}.`
|
|
108
|
+
: "";
|
|
109
|
+
const result = await finalizeAgentBrowserNativeResult({
|
|
110
|
+
content: [
|
|
111
|
+
{
|
|
112
|
+
type: "text",
|
|
113
|
+
text: `${formatSearchResults(details.provider, details.returnedQuery, details.results)}${duplicateNotice}`,
|
|
439
114
|
},
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
}
|
|
449
|
-
function
|
|
450
|
-
if (
|
|
451
|
-
return EXA_DEEP_LITE_SEARCH_REQUEST_TIMEOUT_MS;
|
|
452
|
-
if (searchType === "deep")
|
|
453
|
-
return EXA_DEEP_SEARCH_REQUEST_TIMEOUT_MS;
|
|
454
|
-
if (searchType === "deep-reasoning")
|
|
455
|
-
return EXA_DEEP_REASONING_SEARCH_REQUEST_TIMEOUT_MS;
|
|
456
|
-
return SEARCH_REQUEST_TIMEOUT_MS;
|
|
457
|
-
}
|
|
458
|
-
function usesDynamicHighlights(body) {
|
|
459
|
-
const contents = body.contents;
|
|
460
|
-
if (!contents || typeof contents !== "object" || Array.isArray(contents))
|
|
115
|
+
],
|
|
116
|
+
details: { data: details },
|
|
117
|
+
}, params);
|
|
118
|
+
// Keep the finalized spill receipt while flattening the documented search details shape.
|
|
119
|
+
const finalizedManifest = result.details.artifactManifest;
|
|
120
|
+
return finalizedManifest === undefined
|
|
121
|
+
? { ...result, details }
|
|
122
|
+
: { ...result, details: { ...details, artifactManifest: finalizedManifest } };
|
|
123
|
+
}
|
|
124
|
+
function isNormalizedSearchResult(value) {
|
|
125
|
+
if (!isRecord(value) || typeof value.title !== "string" || typeof value.url !== "string") {
|
|
461
126
|
return false;
|
|
462
|
-
|
|
463
|
-
return
|
|
464
|
-
|
|
465
|
-
export async function fetchExaSearchJson(body, apiKey, signal, timeoutMs = SEARCH_REQUEST_TIMEOUT_MS) {
|
|
466
|
-
return fetchSearchJson({
|
|
467
|
-
apiKey,
|
|
468
|
-
cancelMessage: "Exa search cancelled",
|
|
469
|
-
init: {
|
|
470
|
-
body: JSON.stringify(body),
|
|
471
|
-
headers: {
|
|
472
|
-
Accept: "application/json",
|
|
473
|
-
"Content-Type": "application/json",
|
|
474
|
-
"x-api-key": apiKey,
|
|
475
|
-
...(usesDynamicHighlights(body) ? { "Exa-Beta": EXA_DYNAMIC_HIGHLIGHTS_BETA } : {}),
|
|
476
|
-
},
|
|
477
|
-
method: "POST",
|
|
478
|
-
},
|
|
479
|
-
invalidJsonMessage: "Exa search returned invalid JSON",
|
|
480
|
-
provider: "exa",
|
|
481
|
-
request: EXA_SEARCH_ENDPOINT,
|
|
482
|
-
signal,
|
|
483
|
-
timeoutMessage: "Exa search timed out",
|
|
484
|
-
timeoutMs,
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
const BRAVE_WEB_SEARCH_ADAPTER = {
|
|
488
|
-
provider: "brave",
|
|
489
|
-
buildRequest(params) {
|
|
490
|
-
return buildBraveSearchUrl({
|
|
491
|
-
query: params.query,
|
|
492
|
-
// Brave offsets count pages; fetch the prefix and slice by result like Exa.
|
|
493
|
-
count: params.count + params.offset,
|
|
494
|
-
offset: 0,
|
|
495
|
-
country: params.country,
|
|
496
|
-
searchLang: params.searchLang,
|
|
497
|
-
safesearch: params.safesearch,
|
|
498
|
-
freshness: params.freshness,
|
|
499
|
-
});
|
|
500
|
-
},
|
|
501
|
-
fetchJson(request, apiKey, signal) {
|
|
502
|
-
return fetchBraveSearchJson(request, apiKey, signal);
|
|
503
|
-
},
|
|
504
|
-
normalizeResponse(response, params) {
|
|
505
|
-
return {
|
|
506
|
-
results: (response.web?.results ?? [])
|
|
507
|
-
.map(normalizeBraveSearchResult)
|
|
508
|
-
.filter((result) => Boolean(result))
|
|
509
|
-
.slice(params.offset, params.offset + params.count),
|
|
510
|
-
returnedQuery: cleanSearchText(response.query?.altered, 300) ?? cleanSearchText(response.query?.original, 300) ?? params.query,
|
|
511
|
-
};
|
|
512
|
-
},
|
|
513
|
-
};
|
|
514
|
-
const EXA_WEB_SEARCH_ADAPTER = {
|
|
515
|
-
provider: "exa",
|
|
516
|
-
buildRequest(params) {
|
|
517
|
-
const searchType = params.searchType ?? "auto";
|
|
518
|
-
return {
|
|
519
|
-
body: buildExaSearchRequestBody(params),
|
|
520
|
-
timeoutMs: getExaRequestTimeoutMs(searchType),
|
|
521
|
-
};
|
|
522
|
-
},
|
|
523
|
-
fetchJson(request, apiKey, signal) {
|
|
524
|
-
return fetchExaSearchJson(request.body, apiKey, signal, request.timeoutMs);
|
|
525
|
-
},
|
|
526
|
-
normalizeResponse(response, params) {
|
|
527
|
-
const searchType = params.searchType ?? "auto";
|
|
528
|
-
return {
|
|
529
|
-
extraDetails: {
|
|
530
|
-
requestId: cleanSearchText(response.requestId, 120),
|
|
531
|
-
searchType,
|
|
532
|
-
},
|
|
533
|
-
results: (response.results ?? [])
|
|
534
|
-
.map(normalizeExaSearchResult)
|
|
535
|
-
.filter((result) => Boolean(result))
|
|
536
|
-
.slice(params.offset, params.offset + params.count),
|
|
537
|
-
returnedQuery: params.query,
|
|
538
|
-
};
|
|
539
|
-
},
|
|
540
|
-
};
|
|
541
|
-
const WEB_SEARCH_PROVIDER_ADAPTERS = {
|
|
542
|
-
exa: EXA_WEB_SEARCH_ADAPTER,
|
|
543
|
-
brave: BRAVE_WEB_SEARCH_ADAPTER,
|
|
544
|
-
};
|
|
545
|
-
export function getWebSearchProviderAdapter(provider) {
|
|
546
|
-
return WEB_SEARCH_PROVIDER_ADAPTERS[provider];
|
|
547
|
-
}
|
|
548
|
-
function dedupeSearchResults(results) {
|
|
549
|
-
const seen = new Set();
|
|
550
|
-
return results.filter((result) => {
|
|
551
|
-
if (seen.has(result.url))
|
|
552
|
-
return false;
|
|
553
|
-
seen.add(result.url);
|
|
554
|
-
return true;
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
function buildMissingCredentialError(provider) {
|
|
558
|
-
if (provider === "brave")
|
|
559
|
-
return "agent_browser_web_search provider brave was requested but no BRAVE_API_KEY/config credential resolved.";
|
|
560
|
-
if (provider === "exa")
|
|
561
|
-
return "agent_browser_web_search provider exa was requested but no EXA_API_KEY/config credential resolved.";
|
|
562
|
-
return "No Exa or Brave web search credential resolved. Configure webSearch.exaApiKey or webSearch.braveApiKey, or load EXA_API_KEY/BRAVE_API_KEY in the runtime environment.";
|
|
127
|
+
}
|
|
128
|
+
return (["description", "source", "age", "pageDate", "language"].every((field) => value[field] === undefined || typeof value[field] === "string") &&
|
|
129
|
+
(value.highlights === undefined || isStringArray(value.highlights)));
|
|
563
130
|
}
|
|
564
|
-
|
|
565
|
-
|
|
131
|
+
function failureCategory(error, signal) {
|
|
132
|
+
if (signal?.aborted === true) {
|
|
133
|
+
return "aborted";
|
|
134
|
+
}
|
|
135
|
+
return error instanceof WebSearchLocalError ? "validation-error" : "upstream-error";
|
|
566
136
|
}
|
|
567
137
|
export function createAgentBrowserWebSearchTool(configState, options = {}) {
|
|
568
138
|
const requestGate = new WebSearchRequestGate();
|
|
@@ -576,79 +146,19 @@ export function createAgentBrowserWebSearchTool(configState, options = {}) {
|
|
|
576
146
|
parameters: AgentBrowserWebSearchParams,
|
|
577
147
|
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
578
148
|
try {
|
|
579
|
-
const
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
}
|
|
583
|
-
if (!runtimeConfigState.webSearchEnabled) {
|
|
584
|
-
throw new WebSearchLocalError("agent_browser_web_search is disabled by pi-agent-browser-native config.");
|
|
585
|
-
}
|
|
586
|
-
const requestedProvider = params.provider ?? "auto";
|
|
587
|
-
const resolved = await resolvePreferredWebSearchCredential(runtimeConfigState, { provider: requestedProvider, signal });
|
|
588
|
-
if (!resolved)
|
|
589
|
-
throw new WebSearchLocalError(buildMissingCredentialError(requestedProvider));
|
|
590
|
-
if (resolved.provider === "brave") {
|
|
591
|
-
const exaOnlyFields = [
|
|
592
|
-
params.includeDomains ? "includeDomains" : undefined,
|
|
593
|
-
params.excludeDomains ? "excludeDomains" : undefined,
|
|
594
|
-
params.category ? "category" : undefined,
|
|
595
|
-
params.additionalQueries ? "additionalQueries" : undefined,
|
|
596
|
-
params.highlightsDynamic ? "highlightsDynamic" : undefined,
|
|
597
|
-
].filter((field) => Boolean(field));
|
|
598
|
-
if (exaOnlyFields.length > 0) {
|
|
599
|
-
throw new WebSearchLocalError(`${exaOnlyFields.join(", ")} ${exaOnlyFields.length === 1 ? "requires" : "require"} provider exa; resolved provider was brave.`);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
const query = params.query.trim();
|
|
603
|
-
if (!query)
|
|
604
|
-
throw new WebSearchLocalError("query must not be blank");
|
|
605
|
-
const count = Math.min(Math.max(params.count ?? DEFAULT_SEARCH_RESULT_COUNT, 1), MAX_SEARCH_RESULT_COUNT);
|
|
606
|
-
const offset = Math.max(params.offset ?? 0, 0);
|
|
607
|
-
const adapter = getWebSearchProviderAdapter(resolved.provider);
|
|
608
|
-
const executionParams = {
|
|
609
|
-
additionalQueries: params.additionalQueries,
|
|
610
|
-
category: params.category,
|
|
611
|
-
country: params.country,
|
|
612
|
-
count,
|
|
613
|
-
excludeDomains: params.excludeDomains,
|
|
614
|
-
freshness: params.freshness,
|
|
615
|
-
highlightsDynamic: params.highlightsDynamic,
|
|
616
|
-
includeDomains: params.includeDomains,
|
|
617
|
-
offset,
|
|
618
|
-
query,
|
|
619
|
-
safesearch: params.safesearch,
|
|
620
|
-
searchLang: params.searchLang,
|
|
621
|
-
searchType: params.searchType ?? runtimeConfigState.config.webSearch?.defaultSearchType ?? "auto",
|
|
622
|
-
};
|
|
623
|
-
const request = adapter.buildRequest(executionParams);
|
|
624
|
-
const data = await requestGate.run(signal, () => adapter.fetchJson(request, resolved.credential.value, signal));
|
|
625
|
-
const normalized = adapter.normalizeResponse(data, executionParams);
|
|
626
|
-
const results = dedupeSearchResults(normalized.results);
|
|
627
|
-
const duplicatesRemoved = normalized.results.length - results.length;
|
|
628
|
-
const details = {
|
|
629
|
-
provider: adapter.provider,
|
|
630
|
-
query,
|
|
631
|
-
returnedQuery: normalized.returnedQuery,
|
|
632
|
-
count,
|
|
633
|
-
offset,
|
|
634
|
-
...normalized.extraDetails,
|
|
635
|
-
fetchedAt: new Date().toISOString(),
|
|
636
|
-
results,
|
|
637
|
-
duplicatesRemoved: duplicatesRemoved || undefined,
|
|
638
|
-
};
|
|
639
|
-
const result = await finalizeAgentBrowserNativeResult({
|
|
640
|
-
content: [{ type: "text", text: `${formatSearchResults(adapter.provider, normalized.returnedQuery, results)}${duplicatesRemoved ? `\n\nDuplicate URLs removed: ${duplicatesRemoved}.` : ""}` }],
|
|
641
|
-
details: { data: details },
|
|
642
|
-
}, params);
|
|
643
|
-
// Keep the finalized spill's invocation artifact receipt while flattening the documented search details shape.
|
|
644
|
-
const finalizedManifest = isRecord(result.details) ? result.details.artifactManifest : undefined;
|
|
645
|
-
return finalizedManifest === undefined ? { ...result, details } : { ...result, details: { ...details, artifactManifest: finalizedManifest } };
|
|
149
|
+
const state = ctx ? (options.loadConfigState?.(ctx) ?? configState) : configState;
|
|
150
|
+
const details = await runWebSearch(state, params, requestGate, signal);
|
|
151
|
+
return await presentSearchSuccess(details, params);
|
|
646
152
|
}
|
|
647
153
|
catch (error) {
|
|
648
|
-
const message = redactSensitiveText(error instanceof Error ? error.message :
|
|
154
|
+
const message = redactSensitiveText(error instanceof Error ? error.message : "Unknown web search failure").slice(0, 1_000);
|
|
649
155
|
return finalizeAgentBrowserNativeResult({
|
|
650
156
|
content: [{ type: "text", text: message }],
|
|
651
|
-
details: {
|
|
157
|
+
details: {
|
|
158
|
+
error: message,
|
|
159
|
+
resultCategory: "failure",
|
|
160
|
+
failureCategory: failureCategory(error, signal),
|
|
161
|
+
},
|
|
652
162
|
isError: true,
|
|
653
163
|
}, params);
|
|
654
164
|
}
|