pi-agent-browser-native 0.2.77 → 0.5.0
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 +154 -0
- package/README.md +69 -35
- package/dist/extensions/agent-browser/index.js +911 -121
- package/dist/extensions/agent-browser/lib/argv-descriptor.js +35 -8
- package/dist/extensions/agent-browser/lib/argv-grammar.js +48 -7
- package/dist/extensions/agent-browser/lib/batch-lifecycle.js +71 -0
- package/dist/extensions/agent-browser/lib/command-policy.js +1 -6
- package/dist/extensions/agent-browser/lib/command-taxonomy.js +35 -8
- package/dist/extensions/agent-browser/lib/config-policy.js +0 -5
- package/dist/extensions/agent-browser/lib/config.js +0 -6
- package/dist/extensions/agent-browser/lib/electron/cdp.js +6 -7
- package/dist/extensions/agent-browser/lib/electron/cleanup.js +0 -7
- package/dist/extensions/agent-browser/lib/electron/discovery.js +0 -7
- package/dist/extensions/agent-browser/lib/electron/launch.js +0 -7
- package/dist/extensions/agent-browser/lib/input-modes/electron.js +0 -5
- package/dist/extensions/agent-browser/lib/input-modes/job.js +61 -9
- package/dist/extensions/agent-browser/lib/input-modes/lookups.js +2 -7
- package/dist/extensions/agent-browser/lib/input-modes/params.js +23 -29
- package/dist/extensions/agent-browser/lib/input-modes/script.js +462 -0
- package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +51 -17
- package/dist/extensions/agent-browser/lib/input-modes/shared.js +0 -5
- package/dist/extensions/agent-browser/lib/input-modes/types.js +0 -5
- package/dist/extensions/agent-browser/lib/json-schema.js +0 -5
- package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +12 -5
- package/dist/extensions/agent-browser/lib/managed-session-capabilities.js +0 -2
- package/dist/extensions/agent-browser/lib/managed-session-policy-lock.js +3 -4
- package/dist/extensions/agent-browser/lib/managed-session-restore.js +55 -48
- package/dist/extensions/agent-browser/lib/managed-session-snapshots.js +2 -9
- package/dist/extensions/agent-browser/lib/managed-session-state-policy.js +48 -36
- package/dist/extensions/agent-browser/lib/managed-session-storage.js +50 -29
- package/dist/extensions/agent-browser/lib/navigation-policy.js +0 -5
- package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +26 -5
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +110 -30
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +2 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +27 -26
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +58 -33
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +2 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +22 -14
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/direct-anchor-download.js +1 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +1 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +1 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +1 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +148 -34
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +225 -61
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +74 -30
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +47 -26
- package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +40 -19
- package/dist/extensions/agent-browser/lib/orchestration/output-file.js +42 -1
- package/dist/extensions/agent-browser/lib/orchestration/script-mode.js +299 -0
- package/dist/extensions/agent-browser/lib/parsing.js +0 -7
- package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +36 -11
- package/dist/extensions/agent-browser/lib/playbook.js +20 -24
- package/dist/extensions/agent-browser/lib/process-environment.js +14 -0
- package/dist/extensions/agent-browser/lib/process-identity.js +4 -9
- package/dist/extensions/agent-browser/lib/process.js +131 -48
- package/dist/extensions/agent-browser/lib/prompt-policy.js +171 -27
- package/dist/extensions/agent-browser/lib/recording-reservations.js +183 -0
- package/dist/extensions/agent-browser/lib/results/action-recommendations.js +63 -13
- package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +68 -11
- package/dist/extensions/agent-browser/lib/results/categories.js +7 -9
- package/dist/extensions/agent-browser/lib/results/confirmation.js +0 -7
- package/dist/extensions/agent-browser/lib/results/contracts.js +0 -7
- package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +0 -7
- package/dist/extensions/agent-browser/lib/results/envelope.js +0 -7
- package/dist/extensions/agent-browser/lib/results/network.js +0 -7
- package/dist/extensions/agent-browser/lib/results/next-actions.js +19 -35
- package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +85 -44
- package/dist/extensions/agent-browser/lib/results/presentation/batch.js +66 -11
- package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +0 -5
- package/dist/extensions/agent-browser/lib/results/presentation/common.js +18 -5
- package/dist/extensions/agent-browser/lib/results/presentation/content.js +0 -5
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +7 -6
- package/dist/extensions/agent-browser/lib/results/presentation/errors.js +2 -1
- package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +0 -5
- package/dist/extensions/agent-browser/lib/results/presentation/managed-list-filter.js +0 -5
- package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +26 -16
- package/dist/extensions/agent-browser/lib/results/presentation/registry.js +58 -13
- package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +1 -15
- package/dist/extensions/agent-browser/lib/results/presentation/skills.js +0 -5
- package/dist/extensions/agent-browser/lib/results/presentation.js +6 -8
- package/dist/extensions/agent-browser/lib/results/recovery-actions.js +2 -7
- package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +0 -7
- package/dist/extensions/agent-browser/lib/results/selector-recovery.js +51 -15
- package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +13 -14
- package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +0 -7
- package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +0 -7
- package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +0 -7
- package/dist/extensions/agent-browser/lib/results/snapshot.js +0 -7
- package/dist/extensions/agent-browser/lib/results/text.js +0 -7
- package/dist/extensions/agent-browser/lib/runtime.js +119 -52
- package/dist/extensions/agent-browser/lib/session-page-state.js +62 -17
- package/dist/extensions/agent-browser/lib/string-enum-schema.js +0 -5
- package/dist/extensions/agent-browser/lib/temp.js +0 -7
- package/dist/extensions/agent-browser/lib/upstream-version.js +14 -0
- package/dist/extensions/agent-browser/lib/web-search.js +0 -5
- package/dist/extensions/agent-browser/script-worker.js +169 -0
- package/dist/scripts/agent-browser-target.mjs +3 -0
- package/docs/ARCHITECTURE.md +50 -31
- package/docs/COMMAND_REFERENCE.md +97 -41
- package/docs/ELECTRON.md +3 -19
- package/docs/RELEASE.md +8 -20
- package/docs/REQUIREMENTS.md +8 -6
- package/docs/SUPPORT_MATRIX.md +32 -25
- package/docs/TOOL_CONTRACT.md +107 -64
- package/docs/platform-smoke.md +1 -1
- package/package.json +7 -6
- package/platform-smoke.config.mjs +2 -2
- package/scripts/agent-browser-capability-baseline.mjs +24 -6
- package/scripts/agent-browser-target.mjs +3 -0
- package/scripts/build.mjs +41 -0
- package/scripts/doctor.mjs +8 -7
- package/scripts/platform-smoke/browser-dogfood-windows.ps1 +9 -3
- package/scripts/platform-smoke/targets.mjs +12 -6
- package/dist/extensions/agent-browser/lib/electron/text.js +0 -13
- package/dist/extensions/agent-browser/lib/input-modes.js +0 -10
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-artifacts.js +0 -5
- package/dist/extensions/agent-browser/lib/results/artifact-state.js +0 -13
- package/dist/extensions/agent-browser/lib/results.js +0 -14
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import { copyFile, mkdir } from "node:fs/promises";
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { getBooleanFlagValue, isUpstreamEnvFlagEnabled, projectUpstreamGlobalFlags } from "../../argv-grammar.js";
|
|
3
4
|
import { isCloseCommand } from "../../command-taxonomy.js";
|
|
4
5
|
import { cleanupElectronLaunchResources } from "../../electron/cleanup.js";
|
|
5
6
|
import { launchElectronApp } from "../../electron/launch.js";
|
|
6
7
|
import { pathExists } from "../../fs-utils.js";
|
|
7
|
-
import { getCompiledSemanticActionSessionPrefix } from "../../input-modes.js";
|
|
8
|
+
import { getCompiledSemanticActionSessionPrefix } from "../../input-modes/semantic-action.js";
|
|
8
9
|
import { tryDirectAnchorDownload } from "./prepare/direct-anchor-download.js";
|
|
9
10
|
import { tryNetworkRequestsPageFilter } from "./prepare/network-page-filter.js";
|
|
10
11
|
import { tryContainerScroll, tryPageScrollTo } from "./prepare/scroll-shims.js";
|
|
11
12
|
import { trySnapshotFilter } from "./prepare/snapshot-filter.js";
|
|
12
13
|
import { commandTimeoutNeedsActivePageUrl, getCommandAwareProcessTimeoutMs } from "./prepare/wait-timeouts.js";
|
|
13
|
-
import { getPersistentSessionArtifactStore } from "./session-
|
|
14
|
-
import { buildAgentBrowserResultCategoryDetails } from "../../results.js";
|
|
14
|
+
import { getPersistentSessionArtifactStore } from "./session-state.js";
|
|
15
|
+
import { buildAgentBrowserResultCategoryDetails } from "../../results/categories.js";
|
|
15
16
|
import { applyNamespaceToNextActions } from "../../results/next-actions.js";
|
|
16
17
|
import { buildSessionAwareStaleRefNextActions, buildSessionTabRecoveryNextActions } from "../../results/recovery-next-actions.js";
|
|
17
18
|
import { resolveVisibleRefActionFromSnapshot } from "../../results/selector-recovery.js";
|
|
18
19
|
import { extractRefSnapshotFromData } from "../../session-page-state.js";
|
|
19
|
-
import { buildExecutionPlan, createFreshSessionName, extractCommandTokens, getDefaultHeadlessCompatUserAgent, redactInvocationArgs, } from "../../runtime.js";
|
|
20
|
-
import { buildOwnedManagedSessionRestoreContext, canonicalizeOwnedManagedSessionCloseArgs, withOwnedManagedSessionContext, } from "../../managed-session-restore.js";
|
|
20
|
+
import { buildExecutionPlan, canUseHeadlessCompatibilityUserAgent, createFreshSessionName, extractCommandTokens, extractUpstreamCommandTokens, getDefaultHeadlessCompatUserAgent, parseWaitCommandTokens, redactInvocationArgs, } from "../../runtime.js";
|
|
21
|
+
import { buildOwnedManagedSessionRestoreContext, canonicalizeOwnedManagedSessionCloseArgs, resolveExplicitAutosaveInterval, withOwnedManagedSessionContext, } from "../../managed-session-restore.js";
|
|
22
|
+
import { getAgentBrowserProcessEnvironment } from "../../process-environment.js";
|
|
21
23
|
import { getCallerOwnedSessionLivePageVerificationRequirement, getManagedSessionStateAccessValidationError, getManagedSessionTargetAccessValidationError, } from "../../managed-session-state-policy.js";
|
|
22
|
-
import { acquireOwnedManagedSessionDaemonPolicy } from "./managed-session-daemon-policy.js";
|
|
24
|
+
import { acquireOwnedManagedSessionDaemonPolicy, getRunningHeadedAutosavePolicyChangeError } from "./managed-session-daemon-policy.js";
|
|
23
25
|
import { applyOpenResultTabCorrection, buildManagedSessionOutcome, buildPinnedBatchPlan, buildSessionDetailFields, buildStaleRefPreflight, getSessionContextKey, extractStringResultField, collectAnySessionTabSelection, collectSessionTabSelection, getGuardedRefUsage, getTraceOwnerGuardMessage, runSessionCommandData, shouldPinSessionTabForCommand, } from "./session-state.js";
|
|
24
|
-
import { parseBatchStdinJsonArray } from "../batch-stdin.js";
|
|
26
|
+
import { getUpstreamEffectiveBatchSteps, parseBatchStdinJsonArray } from "../batch-stdin.js";
|
|
25
27
|
import { buildElectronHostFailureResult, getElectronLaunchFailureCategory, redactRecoveryHint } from "./final-result.js";
|
|
26
28
|
import { prepareClickDispatchProbe } from "./click-dispatch.js";
|
|
27
29
|
import { collectScrollPositionSnapshot, validateQaAttachedPrecondition } from "./diagnostics.js";
|
|
@@ -42,6 +44,7 @@ export function normalizeRunInput(input) {
|
|
|
42
44
|
return { ...base, compiledSemanticAction: input.compiledSemanticAction, redactedCompiledSemanticAction: input.redactedCompiledSemanticAction };
|
|
43
45
|
case "sourceLookup":
|
|
44
46
|
return { ...base, compiledSourceLookup: input.compiledSourceLookup, redactedCompiledSourceLookup: input.redactedCompiledSourceLookup };
|
|
47
|
+
case "script":
|
|
45
48
|
case "args":
|
|
46
49
|
return base;
|
|
47
50
|
}
|
|
@@ -57,12 +60,8 @@ function getArtifactParentPathTokenIndex(commandTokens) {
|
|
|
57
60
|
return 1;
|
|
58
61
|
if (commandTokens[0] === "state" && commandTokens[1] === "save" && commandTokens.length >= 3)
|
|
59
62
|
return 2;
|
|
60
|
-
if (commandTokens[0] === "wait")
|
|
61
|
-
|
|
62
|
-
const pathIndex = downloadIndex >= 0 ? downloadIndex + 1 : -1;
|
|
63
|
-
if (pathIndex > 0 && typeof commandTokens[pathIndex] === "string" && !commandTokens[pathIndex].startsWith("-"))
|
|
64
|
-
return pathIndex;
|
|
65
|
-
}
|
|
63
|
+
if (commandTokens[0] === "wait")
|
|
64
|
+
return parseWaitCommandTokens(commandTokens).downloadPathIndex;
|
|
66
65
|
return undefined;
|
|
67
66
|
}
|
|
68
67
|
async function ensureArtifactParentDirectory(commandTokens, cwd) {
|
|
@@ -75,10 +74,14 @@ async function ensureArtifactParentDirectory(commandTokens, cwd) {
|
|
|
75
74
|
await mkdir(dirname(resolve(cwd, requestedPath)), { recursive: true });
|
|
76
75
|
}
|
|
77
76
|
async function normalizeScreenshotPathInTokens(commandTokens, cwd) {
|
|
78
|
-
const
|
|
79
|
-
|
|
77
|
+
const scopedCommandTokens = extractCommandTokens(commandTokens);
|
|
78
|
+
const projection = projectUpstreamGlobalFlags(scopedCommandTokens);
|
|
79
|
+
const projectedPathTokenIndex = getScreenshotPathTokenIndex(projection.tokens);
|
|
80
|
+
const scopedPathTokenIndex = projectedPathTokenIndex === undefined ? undefined : projection.indices[projectedPathTokenIndex];
|
|
81
|
+
if (scopedPathTokenIndex === undefined) {
|
|
80
82
|
return { tokens: commandTokens };
|
|
81
83
|
}
|
|
84
|
+
const screenshotPathTokenIndex = commandTokens.length - scopedCommandTokens.length + scopedPathTokenIndex;
|
|
82
85
|
const requestedPath = commandTokens[screenshotPathTokenIndex];
|
|
83
86
|
const absolutePath = resolve(cwd, requestedPath);
|
|
84
87
|
await mkdir(dirname(absolutePath), { recursive: true });
|
|
@@ -97,8 +100,28 @@ async function normalizeScreenshotPathInTokens(commandTokens, cwd) {
|
|
|
97
100
|
};
|
|
98
101
|
}
|
|
99
102
|
async function prepareBatchScreenshotPaths(args, stdin, cwd) {
|
|
100
|
-
const commandTokens =
|
|
101
|
-
if (commandTokens[0] !== "batch"
|
|
103
|
+
const commandTokens = extractUpstreamCommandTokens(args);
|
|
104
|
+
if (commandTokens[0] !== "batch") {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
const argumentSteps = getUpstreamEffectiveBatchSteps(commandTokens, undefined);
|
|
108
|
+
if (argumentSteps.length > 0) {
|
|
109
|
+
// Upstream executes raw argument steps exclusively and ignores stdin, so
|
|
110
|
+
// prepare parent directories for the rows that will run and skip stdin
|
|
111
|
+
// preparation (no directories for never-executed rows).
|
|
112
|
+
for (const step of argumentSteps) {
|
|
113
|
+
const stepTokens = extractUpstreamCommandTokens(step);
|
|
114
|
+
await ensureArtifactParentDirectory(stepTokens, cwd);
|
|
115
|
+
if (stepTokens[0] === "screenshot") {
|
|
116
|
+
// Reuse the screenshot path resolution for its parent-directory side
|
|
117
|
+
// effect only: raw strings are never rewritten, so the normalized
|
|
118
|
+
// tokens and path request are deliberately discarded.
|
|
119
|
+
await normalizeScreenshotPathInTokens(step, cwd);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
if (stdin === undefined) {
|
|
102
125
|
return undefined;
|
|
103
126
|
}
|
|
104
127
|
const parsed = parseBatchStdinJsonArray(stdin);
|
|
@@ -111,8 +134,9 @@ async function prepareBatchScreenshotPaths(args, stdin, cwd) {
|
|
|
111
134
|
if (!Array.isArray(step) || !step.every((item) => typeof item === "string")) {
|
|
112
135
|
return step;
|
|
113
136
|
}
|
|
114
|
-
|
|
115
|
-
|
|
137
|
+
const upstreamStep = extractUpstreamCommandTokens(step);
|
|
138
|
+
await ensureArtifactParentDirectory(upstreamStep, cwd);
|
|
139
|
+
if (upstreamStep[0] !== "screenshot") {
|
|
116
140
|
return step;
|
|
117
141
|
}
|
|
118
142
|
const normalized = await normalizeScreenshotPathInTokens(step, cwd);
|
|
@@ -136,7 +160,7 @@ export async function prepareAgentBrowserArgs(args, stdin, cwd) {
|
|
|
136
160
|
return preparedBatch;
|
|
137
161
|
}
|
|
138
162
|
const commandTokens = extractCommandTokens(args);
|
|
139
|
-
await ensureArtifactParentDirectory(
|
|
163
|
+
await ensureArtifactParentDirectory(extractUpstreamCommandTokens(args), cwd);
|
|
140
164
|
const normalized = await normalizeScreenshotPathInTokens(commandTokens, cwd);
|
|
141
165
|
if (!normalized.request) {
|
|
142
166
|
return { args };
|
|
@@ -180,7 +204,7 @@ const LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_MS = 8_000;
|
|
|
180
204
|
const LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_ENV = "PI_AGENT_BROWSER_DIALOG_TRIGGER_PROCESS_TIMEOUT_MS";
|
|
181
205
|
const DIALOG_TRIGGER_TEXT_PATTERN = /\b(?:alert|confirm|dialog|prompt)\b/i;
|
|
182
206
|
function getPositiveIntegerEnv(name) {
|
|
183
|
-
const value =
|
|
207
|
+
const value = getAgentBrowserProcessEnvironment()[name];
|
|
184
208
|
if (!value || !/^\d+$/.test(value.trim()))
|
|
185
209
|
return undefined;
|
|
186
210
|
const parsed = Number(value.trim());
|
|
@@ -214,9 +238,7 @@ function describeRef(refSnapshot, refId) {
|
|
|
214
238
|
return ref ? `${ref.role} ${JSON.stringify(ref.name)}` : "not present";
|
|
215
239
|
}
|
|
216
240
|
function getSamePageFreshnessPreflightFailure(options) {
|
|
217
|
-
|
|
218
|
-
return undefined;
|
|
219
|
-
const refIds = getRefIdsFromDirectCommand(options.commandTokens);
|
|
241
|
+
const { refIds } = options;
|
|
220
242
|
if (refIds.length === 0)
|
|
221
243
|
return undefined;
|
|
222
244
|
const previousUrl = options.previousSnapshot.target?.url;
|
|
@@ -242,7 +264,8 @@ function getSamePageFreshnessPreflightFailure(options) {
|
|
|
242
264
|
};
|
|
243
265
|
}
|
|
244
266
|
async function collectSamePageRefFreshnessPreflight(options) {
|
|
245
|
-
|
|
267
|
+
const refIds = [...new Set(getGuardedRefUsage(options.commandTokens, options.stdin))];
|
|
268
|
+
if (!options.previousSnapshot || !options.sessionName || refIds.length === 0)
|
|
246
269
|
return undefined;
|
|
247
270
|
const previousUrl = options.previousSnapshot.target?.url;
|
|
248
271
|
const currentTargetUrl = options.currentTarget?.url;
|
|
@@ -253,7 +276,7 @@ async function collectSamePageRefFreshnessPreflight(options) {
|
|
|
253
276
|
if (!currentSnapshot)
|
|
254
277
|
return undefined;
|
|
255
278
|
const snapshotWithTarget = { ...currentSnapshot, target: currentSnapshot.target ?? options.currentTarget };
|
|
256
|
-
const mismatch = getSamePageFreshnessPreflightFailure({
|
|
279
|
+
const mismatch = getSamePageFreshnessPreflightFailure({ currentSnapshot: snapshotWithTarget, previousSnapshot: options.previousSnapshot, refIds });
|
|
257
280
|
if (!mismatch)
|
|
258
281
|
return undefined;
|
|
259
282
|
return { message: mismatch.message, refIds: mismatch.refIds, snapshot: snapshotWithTarget };
|
|
@@ -296,7 +319,14 @@ export function validateStdinCommandContract(options) {
|
|
|
296
319
|
return `agent_browser stdin is only supported for \`batch\`, \`eval --stdin\`, and \`auth save --password-stdin\`; remove stdin from ${commandLabel} or use one of those command forms.`;
|
|
297
320
|
}
|
|
298
321
|
function canResolveSemanticVisibleRef(compiled) {
|
|
299
|
-
|
|
322
|
+
if (!compiled?.locator)
|
|
323
|
+
return false;
|
|
324
|
+
if (compiled.action === "select")
|
|
325
|
+
return true;
|
|
326
|
+
return compiled.locator === "role" && ["check", "click", "fill"].includes(compiled.action);
|
|
327
|
+
}
|
|
328
|
+
function requiresResolvedSemanticVisibleRef(compiled) {
|
|
329
|
+
return compiled?.action === "select" && compiled.locator !== undefined;
|
|
300
330
|
}
|
|
301
331
|
function resolveSemanticActionVisibleRefArgsFromSnapshot(compiled, snapshotData) {
|
|
302
332
|
if (!canResolveSemanticVisibleRef(compiled))
|
|
@@ -315,6 +345,7 @@ export async function resolveSemanticActionVisibleRefArgs(options) {
|
|
|
315
345
|
export async function prepareBrowserRun(options) {
|
|
316
346
|
const { cwd, onUpdate, params, signal, state } = options;
|
|
317
347
|
const { sessionPageState, traceOwners, managedSessionBaseName, ephemeralSessionSeed } = state;
|
|
348
|
+
const agentBrowserProcessEnv = getAgentBrowserProcessEnvironment();
|
|
318
349
|
let freshSessionOrdinal = state.freshSessionOrdinal;
|
|
319
350
|
const { compiledElectron, compiledJob, compiledNetworkSourceLookup, compiledQaPreset, compiledSemanticAction, compiledSourceLookup, redactedArgs, redactedCompiledElectron, redactedCompiledJob, redactedCompiledNetworkSourceLookup, redactedCompiledQaPreset, redactedCompiledSemanticAction, redactedCompiledSourceLookup, toolArgs, toolStdin, } = normalizeRunInput(options.input);
|
|
320
351
|
let runtimeToolArgs = toolArgs;
|
|
@@ -325,6 +356,7 @@ export async function prepareBrowserRun(options) {
|
|
|
325
356
|
const rawManagedStateAccessError = getManagedSessionStateAccessValidationError({
|
|
326
357
|
args: runtimeToolArgs,
|
|
327
358
|
cwd,
|
|
359
|
+
parentEnv: agentBrowserProcessEnv,
|
|
328
360
|
stdin: runtimeToolStdin,
|
|
329
361
|
trustedFirstBatchTabSelection: true,
|
|
330
362
|
});
|
|
@@ -392,26 +424,67 @@ export async function prepareBrowserRun(options) {
|
|
|
392
424
|
currentPageUrl: plannedSessionPageState.tabTarget?.url,
|
|
393
425
|
pageUrlUnknown: plannedSessionPageState.tabTargetUnknown === true,
|
|
394
426
|
cwd,
|
|
427
|
+
parentEnv: agentBrowserProcessEnv,
|
|
395
428
|
stdin: runtimeToolStdin,
|
|
396
429
|
});
|
|
397
430
|
if (!executionPlan.validationError && managedStateAccessError)
|
|
398
431
|
executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: managedStateAccessError };
|
|
399
432
|
const recordedOwnedSession = ownedSessionKey ? state.ownedManagedSessions.get(ownedSessionKey) : undefined;
|
|
433
|
+
const targetsCurrentManagedSession = state.managedSessionActive
|
|
434
|
+
&& ownedSessionKey === getSessionContextKey(state.managedSessionName, state.managedSessionNamespace);
|
|
435
|
+
const targetsOffCurrentOwnedSession = recordedOwnedSession !== undefined && !targetsCurrentManagedSession;
|
|
436
|
+
const offCurrentLaunchScopedFlags = targetsOffCurrentOwnedSession
|
|
437
|
+
? executionPlan.startupScopedFlags.filter((flag) => flag !== "--namespace")
|
|
438
|
+
: [];
|
|
439
|
+
const offCurrentCompatibilityUpgrade = targetsOffCurrentOwnedSession
|
|
440
|
+
&& executionPlan.compatibilityWorkaround !== undefined
|
|
441
|
+
&& recordedOwnedSession.compatibilityWorkaround === undefined;
|
|
442
|
+
if (targetsOffCurrentOwnedSession && canUseHeadlessCompatibilityUserAgent(preparedArgs.args, agentBrowserProcessEnv)) {
|
|
443
|
+
const compatibilityWorkaround = executionPlan.compatibilityWorkaround ?? recordedOwnedSession.compatibilityWorkaround;
|
|
444
|
+
if (compatibilityWorkaround) {
|
|
445
|
+
const userAgentIndex = executionPlan.effectiveArgs.indexOf("--user-agent");
|
|
446
|
+
executionPlan = {
|
|
447
|
+
...executionPlan,
|
|
448
|
+
compatibilityWorkaround,
|
|
449
|
+
effectiveArgs: userAgentIndex < 0
|
|
450
|
+
? executionPlan.effectiveArgs
|
|
451
|
+
: [...executionPlan.effectiveArgs.slice(0, userAgentIndex), ...executionPlan.effectiveArgs.slice(userAgentIndex + 2)],
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
const retainedHeadedAutosaveDisabled = recordedOwnedSession?.headedManagedAutosaveDisabled === true
|
|
456
|
+
|| (targetsCurrentManagedSession && state.managedSessionHeadedAutosaveDisabled === true);
|
|
457
|
+
const retainedHeadedAutosaveInterval = recordedOwnedSession?.headedManagedAutosaveInterval
|
|
458
|
+
?? (targetsCurrentManagedSession ? state.managedSessionHeadedAutosaveInterval : undefined);
|
|
459
|
+
const explicitAutosaveInterval = resolveExplicitAutosaveInterval(agentBrowserProcessEnv.AGENT_BROWSER_AUTOSAVE_INTERVAL_MS);
|
|
460
|
+
const autosavePolicyChangeError = getRunningHeadedAutosavePolicyChangeError(retainedHeadedAutosaveInterval, isCloseCommand(executionPlan.commandInfo.command));
|
|
461
|
+
if (!executionPlan.validationError && autosavePolicyChangeError) {
|
|
462
|
+
executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: autosavePolicyChangeError };
|
|
463
|
+
}
|
|
464
|
+
const headedLaunch = getBooleanFlagValue(executionPlan.effectiveArgs, "--headed") ?? isUpstreamEnvFlagEnabled(agentBrowserProcessEnv.AGENT_BROWSER_HEADED);
|
|
465
|
+
const headedManagedAutosaveDisabled = retainedHeadedAutosaveDisabled || (explicitAutosaveInterval === undefined && headedLaunch);
|
|
466
|
+
const headedManagedAutosaveInterval = retainedHeadedAutosaveInterval ?? (headedLaunch ? explicitAutosaveInterval ?? "0" : undefined);
|
|
467
|
+
const compatibilityUserAgent = executionPlan.compatibilityWorkaround ? getDefaultHeadlessCompatUserAgent() : undefined;
|
|
468
|
+
const compatibilityUserAgentApplied = compatibilityUserAgent !== undefined
|
|
469
|
+
&& executionPlan.effectiveArgs.some((token, index) => token === "--user-agent" && executionPlan.effectiveArgs[index + 1] === compatibilityUserAgent);
|
|
400
470
|
const ownedManagedSession = buildOwnedManagedSessionRestoreContext({
|
|
401
471
|
args: executionPlan.effectiveArgs,
|
|
402
472
|
cwd: recordedOwnedSession?.cwd ?? cwd,
|
|
403
473
|
currentManagedSessionName: state.managedSessionName,
|
|
404
474
|
currentManagedSessionNamespace: state.managedSessionNamespace,
|
|
475
|
+
headedManagedAutosaveDisabled,
|
|
476
|
+
headedManagedAutosaveInterval,
|
|
405
477
|
managedSessionName: executionPlan.managedSessionName,
|
|
406
478
|
namespace: executionPlan.namespace,
|
|
479
|
+
parentEnv: agentBrowserProcessEnv,
|
|
407
480
|
recordedOwnedSession,
|
|
408
481
|
restoreState: state.managedSessionRestoreState,
|
|
409
482
|
sessionName: executionPlan.sessionName,
|
|
410
483
|
stdin: runtimeToolStdin,
|
|
411
|
-
compatibilityUserAgent:
|
|
412
|
-
wrapperInjectedUserAgent:
|
|
484
|
+
compatibilityUserAgent: compatibilityUserAgentApplied ? compatibilityUserAgent : undefined,
|
|
485
|
+
wrapperInjectedUserAgent: compatibilityUserAgentApplied,
|
|
413
486
|
});
|
|
414
|
-
const managedSessionTargetError = getManagedSessionTargetAccessValidationError(executionPlan.effectiveArgs, ownedManagedSession !== undefined);
|
|
487
|
+
const managedSessionTargetError = getManagedSessionTargetAccessValidationError(executionPlan.effectiveArgs, ownedManagedSession !== undefined, agentBrowserProcessEnv);
|
|
415
488
|
if (!executionPlan.validationError && managedSessionTargetError)
|
|
416
489
|
executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: managedSessionTargetError };
|
|
417
490
|
if (!executionPlan.validationError && ownedManagedSession) {
|
|
@@ -429,6 +502,27 @@ export async function prepareBrowserRun(options) {
|
|
|
429
502
|
validationError: policy.error,
|
|
430
503
|
};
|
|
431
504
|
}
|
|
505
|
+
else if (!closeCommand && policy.daemonStatus === "active" && offCurrentLaunchScopedFlags.length > 0) {
|
|
506
|
+
executionPlan = {
|
|
507
|
+
...executionPlan,
|
|
508
|
+
recoveryHint: undefined,
|
|
509
|
+
validationError: `This older wrapper-owned session is already running, so launch-scoped flags ${offCurrentLaunchScopedFlags.join(", ")} would replace or be ignored by upstream agent-browser. Close it first, or remove the explicit --session and retry with sessionMode: \"fresh\".`,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
else if (!closeCommand && policy.daemonStatus === "active" && offCurrentCompatibilityUpgrade) {
|
|
513
|
+
executionPlan = {
|
|
514
|
+
...executionPlan,
|
|
515
|
+
recoveryHint: undefined,
|
|
516
|
+
validationError: "This older wrapper-owned session is already running without the user agent required by this site. Close it first, or remove the explicit --session and retry with sessionMode: \"fresh\".",
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
else if (!closeCommand && policy.daemonStatus === "inactive" && compatibilityUserAgent && !compatibilityUserAgentApplied) {
|
|
520
|
+
ownedManagedSession.compatibilityUserAgent = compatibilityUserAgent;
|
|
521
|
+
executionPlan = {
|
|
522
|
+
...executionPlan,
|
|
523
|
+
effectiveArgs: ["--user-agent", compatibilityUserAgent, ...executionPlan.effectiveArgs],
|
|
524
|
+
};
|
|
525
|
+
}
|
|
432
526
|
else if (closeCommand && managedSessionPolicyLock) {
|
|
433
527
|
executionPlan = {
|
|
434
528
|
...executionPlan,
|
|
@@ -488,6 +582,7 @@ export async function prepareBrowserRun(options) {
|
|
|
488
582
|
currentPageUrl: liveUrl,
|
|
489
583
|
cwd,
|
|
490
584
|
pageUrlUnknown: false,
|
|
585
|
+
parentEnv: agentBrowserProcessEnv,
|
|
491
586
|
stdin: request.stdin,
|
|
492
587
|
});
|
|
493
588
|
if (livePageValidationError) {
|
|
@@ -498,7 +593,8 @@ export async function prepareBrowserRun(options) {
|
|
|
498
593
|
priorSessionTabTarget ??= { url: liveUrl };
|
|
499
594
|
priorSessionTabTargetUnknown = undefined;
|
|
500
595
|
};
|
|
501
|
-
const
|
|
596
|
+
const hasPotentialLiveSemanticSession = state.managedSessionActive || priorSessionTabTarget !== undefined || isCallerOwnedExplicitSession() || options.preserveAttachedBrowserSession === true;
|
|
597
|
+
const mayResolveSemanticVisibleRef = executionPlan.managedSessionName !== freshSessionName && hasPotentialLiveSemanticSession && canResolveSemanticVisibleRef(compiledSemanticAction);
|
|
502
598
|
if (!executionPlan.validationError && mayResolveSemanticVisibleRef && requiresLivePageVerification()) {
|
|
503
599
|
await verifyLivePage({
|
|
504
600
|
args: ["snapshot", "-i"],
|
|
@@ -514,6 +610,17 @@ export async function prepareBrowserRun(options) {
|
|
|
514
610
|
signal,
|
|
515
611
|
});
|
|
516
612
|
}
|
|
613
|
+
if (!executionPlan.validationError && requiresResolvedSemanticVisibleRef(compiledSemanticAction) && !semanticActionVisibleRefResolution) {
|
|
614
|
+
const freshLocatorError = executionPlan.managedSessionName === freshSessionName
|
|
615
|
+
? "semanticAction select with locator cannot resolve a current @ref in sessionMode fresh. Open the page first, then reuse that session, or pass selector plus value/values."
|
|
616
|
+
: undefined;
|
|
617
|
+
executionPlan = {
|
|
618
|
+
...executionPlan,
|
|
619
|
+
validationError: freshLocatorError ?? (hasPotentialLiveSemanticSession
|
|
620
|
+
? "semanticAction select with locator could not resolve to exactly one current visible combobox/listbox ref. Run snapshot -i and retry with selector or a more specific role/name."
|
|
621
|
+
: "semanticAction select with locator requires an active browser session so the wrapper can resolve a current @ref; open a page first or pass selector plus value/values."),
|
|
622
|
+
};
|
|
623
|
+
}
|
|
517
624
|
if (semanticActionVisibleRefResolution) {
|
|
518
625
|
executionPlan = buildExecutionPlan(semanticActionVisibleRefResolution.args, {
|
|
519
626
|
freshSessionName,
|
|
@@ -524,7 +631,7 @@ export async function prepareBrowserRun(options) {
|
|
|
524
631
|
sessionMode,
|
|
525
632
|
});
|
|
526
633
|
}
|
|
527
|
-
const commandTokens = semanticActionVisibleRefResolution ?
|
|
634
|
+
const commandTokens = semanticActionVisibleRefResolution ? extractUpstreamCommandTokens(semanticActionVisibleRefResolution.args) : extractUpstreamCommandTokens(preparedArgs.args);
|
|
528
635
|
const resolvedSemanticActionRefSnapshot = semanticActionVisibleRefResolution?.snapshot
|
|
529
636
|
? { ...semanticActionVisibleRefResolution.snapshot, target: semanticActionVisibleRefResolution.snapshot.target ?? priorSessionTabTarget }
|
|
530
637
|
: undefined;
|
|
@@ -679,6 +786,7 @@ export async function prepareBrowserRun(options) {
|
|
|
679
786
|
cwd,
|
|
680
787
|
currentTarget: priorSessionTabTarget,
|
|
681
788
|
previousSnapshot: resolvedSemanticActionRefSnapshot ? undefined : priorRefSnapshotState,
|
|
789
|
+
stdin: runtimeToolStdin,
|
|
682
790
|
namespace: executionPlan.namespace,
|
|
683
791
|
sessionName: executionPlan.sessionName,
|
|
684
792
|
signal,
|
|
@@ -904,7 +1012,11 @@ export async function prepareBrowserRun(options) {
|
|
|
904
1012
|
}
|
|
905
1013
|
if (pinnedBatchPlan) {
|
|
906
1014
|
sessionTabCorrection = plannedSessionTabSelection;
|
|
907
|
-
|
|
1015
|
+
// The rewritten batch must keep the caller's fail-fast semantics:
|
|
1016
|
+
// upstream reads only the exact --bail token, so re-emit it whenever
|
|
1017
|
+
// the original batch tokens carried it (argv or stdin/job/qa mode).
|
|
1018
|
+
const pinnedBailArgs = commandTokens.includes("--bail") ? ["--bail"] : [];
|
|
1019
|
+
processArgs = ["--json", ...(executionPlan.namespace !== undefined ? ["--namespace", executionPlan.namespace] : []), "--session", executionPlan.sessionName, "batch", ...pinnedBailArgs];
|
|
908
1020
|
processStdin = JSON.stringify(pinnedBatchPlan.steps);
|
|
909
1021
|
includePinnedNavigationSummary = pinnedBatchPlan.includeNavigationSummary;
|
|
910
1022
|
pinnedBatchUnwrapMode = pinnedBatchPlan.unwrapMode;
|
|
@@ -973,7 +1085,9 @@ export async function prepareBrowserRun(options) {
|
|
|
973
1085
|
redactedCompiledJob,
|
|
974
1086
|
redactedCompiledNetworkSourceLookup,
|
|
975
1087
|
redactedCompiledQaPreset,
|
|
976
|
-
redactedCompiledSemanticAction
|
|
1088
|
+
redactedCompiledSemanticAction: semanticActionVisibleRefResolution && redactedCompiledSemanticAction?.action === "select"
|
|
1089
|
+
? { ...redactedCompiledSemanticAction, args: redactInvocationArgs(semanticActionVisibleRefResolution.args) }
|
|
1090
|
+
: redactedCompiledSemanticAction,
|
|
977
1091
|
redactedCompiledSourceLookup,
|
|
978
1092
|
redactedEffectiveArgs,
|
|
979
1093
|
redactedProcessArgs,
|