pi-agent-browser-native 0.6.6 → 0.6.8
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 +40 -1
- package/README.md +21 -6
- package/dist/extensions/agent-browser/index.js +138 -75
- package/dist/extensions/agent-browser/lib/command-taxonomy.js +6 -5
- package/dist/extensions/agent-browser/lib/electron/cleanup.js +10 -1
- package/dist/extensions/agent-browser/lib/input-modes/params.js +20 -7
- package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +0 -1
- package/dist/extensions/agent-browser/lib/managed-session-restore.js +13 -12
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +6 -25
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +2 -2
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +2 -3
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +10 -3
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +3 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +1 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +104 -117
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +64 -36
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +100 -135
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +3 -1
- package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +3 -1
- package/dist/extensions/agent-browser/lib/page-target-validation.js +10 -10
- package/dist/extensions/agent-browser/lib/parsing.js +7 -0
- package/dist/extensions/agent-browser/lib/playbook.js +6 -9
- package/dist/extensions/agent-browser/lib/process.js +28 -113
- package/dist/extensions/agent-browser/lib/recording-reservations.js +3 -1
- package/dist/extensions/agent-browser/lib/results/action-recommendations.js +5 -2
- package/dist/extensions/agent-browser/lib/results/envelope.js +9 -4
- package/dist/extensions/agent-browser/lib/results/next-actions.js +8 -0
- package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +45 -43
- package/dist/extensions/agent-browser/lib/results/presentation/batch.js +2 -1
- package/dist/extensions/agent-browser/lib/results/presentation/errors.js +10 -2
- package/dist/extensions/agent-browser/lib/results/presentation.js +9 -2
- package/dist/extensions/agent-browser/lib/results/recovery-actions.js +4 -4
- package/dist/extensions/agent-browser/lib/runtime.js +18 -2
- package/dist/extensions/agent-browser/lib/session-page-state.js +29 -10
- package/docs/ARCHITECTURE.md +8 -5
- package/docs/COMMAND_REFERENCE.md +25 -16
- package/docs/ELECTRON.md +6 -6
- package/docs/RELEASE.md +14 -5
- package/docs/REQUIREMENTS.md +1 -1
- package/docs/SUPPORT_MATRIX.md +18 -5
- package/docs/TOOL_CONTRACT.md +38 -25
- package/package.json +5 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import { extractUpstreamCommandTokens, parseCommandInfo } from "./argv-descriptor.js";
|
|
3
|
-
import { canonicalizeAgentBrowserNamespace, extractExplicitNamespace, extractExplicitSessionName, extractRequestedRestoreKey, getAgentBrowserSessionIdentityKey, isUpstreamEnvFlagEnabled, scanUpstreamGlobalFlagOccurrences, } from "./argv-grammar.js";
|
|
3
|
+
import { canonicalizeAgentBrowserNamespace, extractExplicitNamespace, extractExplicitSessionName, extractRequestedRestoreKey, getAgentBrowserSessionIdentityKey, isUpstreamEnvFlagEnabled, resolveAgentBrowserNamespace, scanUpstreamGlobalFlagOccurrences, } from "./argv-grammar.js";
|
|
4
4
|
import { hasLaunchScopedFlagToken, MANAGED_RESTORE_INCOMPATIBLE_BOOLEAN_ENVS, MANAGED_RESTORE_INCOMPATIBLE_ENVS, MANAGED_RESTORE_INCOMPATIBLE_FLAGS, } from "./launch-scoped-flags.js";
|
|
5
5
|
import { createManagedSessionRestoreKey, ensureManagedSessionRestoreStorageIsSecure, getManagedSessionRestoreScope, getManagedSessionRestoreProtectedStorageEnv, hasManagedSessionRestoreProjectIdentity, resolveManagedSessionRestoreHome, } from "./managed-session-storage.js";
|
|
6
6
|
import { parseUserBatchStdin } from "./orchestration/batch-stdin.js";
|
|
@@ -11,7 +11,7 @@ const AGENT_BROWSER_CONFIG_ENV = "AGENT_BROWSER_CONFIG";
|
|
|
11
11
|
const AGENT_BROWSER_RESTORE_ENV = "AGENT_BROWSER_RESTORE";
|
|
12
12
|
const MANAGED_SESSION_RESTORE_ENV = "PI_AGENT_BROWSER_MANAGED_SESSION_RESTORE";
|
|
13
13
|
export const MANAGED_SESSION_NAME_PREFIX = "piab-";
|
|
14
|
-
const MANAGED_SESSION_RESTORE_SPAWN_PINNED_ENVS = new Set([AGENT_BROWSER_CONFIG_ENV, AGENT_BROWSER_RESTORE_ENV
|
|
14
|
+
const MANAGED_SESSION_RESTORE_SPAWN_PINNED_ENVS = new Set([AGENT_BROWSER_CONFIG_ENV, AGENT_BROWSER_RESTORE_ENV]);
|
|
15
15
|
function isDisabledEnvFlag(value) {
|
|
16
16
|
if (value === undefined)
|
|
17
17
|
return false;
|
|
@@ -86,12 +86,13 @@ export function resolveOwnedManagedSessionContext(options) {
|
|
|
86
86
|
}
|
|
87
87
|
return undefined;
|
|
88
88
|
}
|
|
89
|
-
function ownedContextMatches(sessionName,
|
|
89
|
+
function ownedContextMatches(sessionName, args) {
|
|
90
90
|
const owned = ownedManagedSessionStorage.getStore();
|
|
91
|
-
return owned && sessionName === owned.sessionName
|
|
91
|
+
return owned && sessionName === owned.sessionName
|
|
92
|
+
&& canonicalizeAgentBrowserNamespace(resolveAgentBrowserNamespace(args, owned.namespace)) === owned.namespace ? owned : undefined;
|
|
92
93
|
}
|
|
93
94
|
export function isOwnedManagedSessionTarget(args) {
|
|
94
|
-
return ownedContextMatches(extractExplicitSessionName(args),
|
|
95
|
+
return ownedContextMatches(extractExplicitSessionName(args), args) !== undefined;
|
|
95
96
|
}
|
|
96
97
|
function hasExplicitConfigArg(args) {
|
|
97
98
|
return scanUpstreamGlobalFlagOccurrences(args, "--config").length > 0;
|
|
@@ -141,7 +142,7 @@ function managedSessionRestoreOptedOut(options) {
|
|
|
141
142
|
const effectiveEnv = { ...(options.parentEnv ?? getAgentBrowserProcessEnvironment()), ...options.env };
|
|
142
143
|
return isDisabledEnvFlag(effectiveEnv[MANAGED_SESSION_RESTORE_ENV]);
|
|
143
144
|
}
|
|
144
|
-
function isManagedSessionRestoreIncompatible(options) {
|
|
145
|
+
function isManagedSessionRestoreIncompatible(options, namespace = extractExplicitNamespace(options.args)) {
|
|
145
146
|
if (hasManagedSessionRestoreLaunchConflict(options))
|
|
146
147
|
return true;
|
|
147
148
|
if (managedSessionRestoreOptedOut(options))
|
|
@@ -152,13 +153,13 @@ function isManagedSessionRestoreIncompatible(options) {
|
|
|
152
153
|
return true;
|
|
153
154
|
if (options.cwd && agentBrowserConfigBlocksManagedRestore(options.cwd, effectiveEnv, args))
|
|
154
155
|
return true;
|
|
155
|
-
return !ensureManagedSessionRestoreStorageIsSecure(effectiveEnv, process.platform,
|
|
156
|
+
return !ensureManagedSessionRestoreStorageIsSecure(effectiveEnv, process.platform, namespace);
|
|
156
157
|
}
|
|
157
158
|
function resolveManagedSessionRestorePolicy(options) {
|
|
158
159
|
const parentEnv = options.parentEnv ?? getAgentBrowserProcessEnvironment();
|
|
159
160
|
const sessionName = extractExplicitSessionName(options.args);
|
|
160
|
-
const
|
|
161
|
-
const
|
|
161
|
+
const ownedContext = ownedContextMatches(sessionName, options.args);
|
|
162
|
+
const namespace = ownedContext ? ownedContext.namespace : extractExplicitNamespace(options.args);
|
|
162
163
|
const restoreState = ownedContext?.restoreState ?? options.restoreState;
|
|
163
164
|
const owned = (options.ownedManagedSession || ownedContext !== undefined) && restoreState !== undefined;
|
|
164
165
|
return { namespace, owned, ownedContext, parentEnv, restoreState, sessionName };
|
|
@@ -234,7 +235,7 @@ export function getManagedSessionRestoreEnv(options) {
|
|
|
234
235
|
return { [AGENT_BROWSER_RESTORE_ENV]: ownedContext.restoreKey };
|
|
235
236
|
}
|
|
236
237
|
const policyOptions = { ...options, parentEnv };
|
|
237
|
-
if (managedSessionRestoreOptedOut(policyOptions) || ownedContext?.restoreSuppressed || isManagedSessionRestoreIncompatible(policyOptions))
|
|
238
|
+
if (managedSessionRestoreOptedOut(policyOptions) || ownedContext?.restoreSuppressed || isManagedSessionRestoreIncompatible(policyOptions, namespace))
|
|
238
239
|
return {};
|
|
239
240
|
if (restoreState.isDisabled(sessionName, namespace) || !sessionName)
|
|
240
241
|
return {};
|
|
@@ -263,7 +264,7 @@ export function commitManagedSessionRestoreSuppression(options) {
|
|
|
263
264
|
return;
|
|
264
265
|
}
|
|
265
266
|
const policyOptions = { ...options, parentEnv };
|
|
266
|
-
if (managedSessionRestoreOptedOut(policyOptions) || ownedContext?.restoreSuppressed || isManagedSessionRestoreIncompatible(policyOptions))
|
|
267
|
+
if (managedSessionRestoreOptedOut(policyOptions) || ownedContext?.restoreSuppressed || isManagedSessionRestoreIncompatible(policyOptions, namespace))
|
|
267
268
|
restoreState.disable(sessionName, namespace);
|
|
268
269
|
}
|
|
269
270
|
export function buildOwnedManagedSessionRestoreContext(options) {
|
|
@@ -281,7 +282,7 @@ export function buildOwnedManagedSessionRestoreContext(options) {
|
|
|
281
282
|
};
|
|
282
283
|
const optedOut = managedSessionRestoreOptedOut(policyOptions);
|
|
283
284
|
const projectIdentityAvailable = !optedOut && hasManagedSessionRestoreProjectIdentity(ownedCwd);
|
|
284
|
-
const incompatible = !optedOut && isManagedSessionRestoreIncompatible(policyOptions);
|
|
285
|
+
const incompatible = !optedOut && isManagedSessionRestoreIncompatible(policyOptions, owned.namespace);
|
|
285
286
|
const enabled = !optedOut && !incompatible;
|
|
286
287
|
const effectiveEnv = { ...(options.parentEnv ?? getAgentBrowserProcessEnvironment()), ...options.env };
|
|
287
288
|
const restoreScope = getManagedSessionRestoreScope(owned.sessionName);
|
|
@@ -1,45 +1,28 @@
|
|
|
1
|
-
import { isRecord } from "../../parsing.js";
|
|
1
|
+
import { isRecord, parseRefId } from "../../parsing.js";
|
|
2
2
|
import { redactSensitiveText } from "../../runtime.js";
|
|
3
3
|
import { withOptionalSessionArgs } from "../../results/next-actions.js";
|
|
4
4
|
import { runSessionCommandData } from "./session-state.js";
|
|
5
5
|
const CLICK_DISPATCH_MARKER_PREFIX = "__piAgentBrowserClickDispatchProbe_";
|
|
6
6
|
const CLICK_DISPATCH_CLEANUP_TIMEOUT_MS = 2_000;
|
|
7
7
|
const ACCESSIBLE_REF_CLICK_DISPATCH_ROLES = new Set(["button", "checkbox", "menuitem", "radio", "switch", "tab"]);
|
|
8
|
-
function parseClickRefId(selector) {
|
|
9
|
-
const trimmed = selector.trim();
|
|
10
|
-
const candidate = trimmed.startsWith("@") ? trimmed.slice(1) : trimmed.startsWith("ref=") ? trimmed.slice(4) : trimmed;
|
|
11
|
-
return /^e\d+$/.test(candidate) ? candidate : undefined;
|
|
12
|
-
}
|
|
13
8
|
function normalizeAccessibleName(name) {
|
|
14
9
|
return name.replace(/\s+/g, " ").trim().toLowerCase();
|
|
15
10
|
}
|
|
16
|
-
function getAccessibleRefDuplicateIndex(refSnapshot, refId, role, name) {
|
|
17
|
-
if (!refSnapshot?.refs)
|
|
18
|
-
return undefined;
|
|
19
|
-
const normalizedRole = role.toLowerCase();
|
|
20
|
-
const normalizedName = normalizeAccessibleName(name);
|
|
21
|
-
const matchingRefIds = refSnapshot.refIds.filter((candidateRefId) => {
|
|
22
|
-
const candidate = refSnapshot.refs?.[candidateRefId];
|
|
23
|
-
return candidate?.role.toLowerCase() === normalizedRole && normalizeAccessibleName(candidate.name) === normalizedName;
|
|
24
|
-
});
|
|
25
|
-
if (matchingRefIds.length <= 1)
|
|
26
|
-
return undefined;
|
|
27
|
-
const duplicateIndex = matchingRefIds.indexOf(refId);
|
|
28
|
-
return duplicateIndex >= 0 ? duplicateIndex : undefined;
|
|
29
|
-
}
|
|
30
11
|
function getClickDispatchProbeTarget(commandTokens, refSnapshot) {
|
|
31
12
|
if (commandTokens[0] !== "click" || commandTokens.includes("--new-tab"))
|
|
32
13
|
return undefined;
|
|
33
14
|
const selector = commandTokens[1];
|
|
34
15
|
if (!selector || selector.startsWith("-"))
|
|
35
16
|
return undefined;
|
|
36
|
-
const refId =
|
|
17
|
+
const refId = parseRefId(selector);
|
|
37
18
|
if (refId) {
|
|
38
19
|
const ref = refSnapshot?.refs?.[refId];
|
|
39
20
|
if (!ref || !ACCESSIBLE_REF_CLICK_DISPATCH_ROLES.has(ref.role))
|
|
40
21
|
return undefined;
|
|
41
|
-
const
|
|
42
|
-
|
|
22
|
+
const matchingRefs = Object.values(refSnapshot?.refs ?? {}).filter((candidate) => candidate.role.toLowerCase() === ref.role.toLowerCase() && normalizeAccessibleName(candidate.name) === normalizeAccessibleName(ref.name));
|
|
23
|
+
if (matchingRefs.length !== 1)
|
|
24
|
+
return undefined;
|
|
25
|
+
return { kind: "accessible", name: ref.name, refId, role: ref.role };
|
|
43
26
|
}
|
|
44
27
|
if (selector.startsWith("xpath="))
|
|
45
28
|
return { kind: "xpath", selector: selector.slice("xpath=".length) };
|
|
@@ -58,7 +41,6 @@ function buildClickDispatchProbeInstallScript(probe) {
|
|
|
58
41
|
const normalize = (value) => String(value ?? "").replace(/\\s+/g, " ").trim();
|
|
59
42
|
const expectedRole = ${JSON.stringify(target.role)};
|
|
60
43
|
const expectedName = normalize(${JSON.stringify(target.name)});
|
|
61
|
-
const duplicateIndex = ${JSON.stringify(target.duplicateIndex)};
|
|
62
44
|
const inferRole = (element) => {
|
|
63
45
|
const explicit = element.getAttribute("role");
|
|
64
46
|
if (explicit) return explicit;
|
|
@@ -81,7 +63,6 @@ function buildClickDispatchProbeInstallScript(probe) {
|
|
|
81
63
|
return element.getClientRects().length > 0;
|
|
82
64
|
};
|
|
83
65
|
const candidates = Array.from(document.querySelectorAll("button,a[href],input,select,textarea,summary,[role],[onclick],[tabindex]")).filter((element) => inferRole(element) === expectedRole && inferName(element) === expectedName && isVisible(element));
|
|
84
|
-
if (typeof duplicateIndex === "number") return candidates[duplicateIndex] || null;
|
|
85
66
|
return candidates.length === 1 ? candidates[0] : null;
|
|
86
67
|
})()`;
|
|
87
68
|
return `(() => {
|
|
@@ -4,7 +4,7 @@ import { isCloseCommand, isOpenNavigationCommand } from "../../command-taxonomy.
|
|
|
4
4
|
import { boundElectronProbeString } from "../../electron/cdp.js";
|
|
5
5
|
import { executableExistsOnPath } from "../../executable-path.js";
|
|
6
6
|
import { formatSessionArtifactRetentionSummary } from "../../results/artifact-manifest.js";
|
|
7
|
-
import { buildNextToolAction, withOptionalSessionArgs } from "../../results/next-actions.js";
|
|
7
|
+
import { buildInspectOverlayStateAction, buildNextToolAction, withOptionalSessionArgs } from "../../results/next-actions.js";
|
|
8
8
|
import { buildVisibleRefFallbackDiagnosticFromSnapshot, getVisibleRefFallbackTarget } from "../../results/selector-recovery.js";
|
|
9
9
|
import { extractRefSnapshotFromData, isAboutBlankUrl, normalizeComparableUrl } from "../../session-page-state.js";
|
|
10
10
|
import { extractUpstreamCommandTokens, parseWaitCommandTokens, redactInvocationArgs, redactSensitiveText } from "../../runtime.js";
|
|
@@ -266,7 +266,7 @@ export function formatOverlayBlockerText(diagnostic) {
|
|
|
266
266
|
return ["Possible overlay blockers:", ...diagnostic.candidates.map((candidate) => `- ${candidate.ref}${candidate.role ? ` ${candidate.role}` : ""}${candidate.name ? ` ${JSON.stringify(candidate.name)}` : ""}: ${candidate.reason}`)].join("\n");
|
|
267
267
|
}
|
|
268
268
|
export function buildOverlayBlockerNextActions(options) {
|
|
269
|
-
return [
|
|
269
|
+
return [buildInspectOverlayStateAction(options.sessionName), ...options.diagnostic.candidates.map((candidate, index) => ({ id: `try-overlay-blocker-candidate-${index + 1}`, params: { args: withOptionalSessionArgs(options.sessionName, candidate.args) }, reason: candidate.reason, safety: "Only click this if the candidate is clearly a close/dismiss control for an overlay that blocks the intended workflow.", tool: "agent_browser" }))];
|
|
270
270
|
}
|
|
271
271
|
export function collectSnapshotOverlayBlockerDiagnostic(data) {
|
|
272
272
|
const candidates = getOverlayBlockerCandidates(data);
|
|
@@ -54,10 +54,9 @@ export function buildSemanticActionCandidateActions(compiled) {
|
|
|
54
54
|
return [];
|
|
55
55
|
}
|
|
56
56
|
export function buildWrapperRecoveryHint(options) {
|
|
57
|
-
|
|
58
|
-
if (wrapperManagedContexts.length === 0)
|
|
57
|
+
if (!options.sessionTabCorrection)
|
|
59
58
|
return undefined;
|
|
60
|
-
return
|
|
59
|
+
return "Wrapper recovery hint: this call used session tab correction. Inspect details.effectiveArgs and details.sessionTabCorrection; if the selected tab looks wrong, run tab list for the same session before retrying.";
|
|
61
60
|
}
|
|
62
61
|
export function redactExactSensitiveText(text, sensitiveValues) {
|
|
63
62
|
let redacted = text;
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { runAgentBrowserProcess, withAttachedBrowserSessionContext } from "../../process.js";
|
|
2
|
+
import { isRecord } from "../../parsing.js";
|
|
2
3
|
import { withOwnedManagedSessionContext } from "../../managed-session-restore.js";
|
|
3
4
|
import { cleanupClickDispatchProbe } from "./click-dispatch.js";
|
|
4
|
-
import { applyBrowserRunStatePatch } from "./session-state.js";
|
|
5
|
+
import { applyBrowserRunStatePatch, getSessionContextKey } from "./session-state.js";
|
|
5
6
|
import { buildMissingBinaryFailureResult } from "./final-result.js";
|
|
6
7
|
import { prepareBrowserRun } from "./prepare.js";
|
|
7
8
|
import { processBrowserOutput } from "./process-output.js";
|
|
8
9
|
export { closeManagedSession } from "./managed-session-daemon-policy.js";
|
|
9
10
|
export { getSessionContextKey } from "./session-state.js";
|
|
10
11
|
export async function runAgentBrowserTool(options) {
|
|
11
|
-
|
|
12
|
+
const result = await withAttachedBrowserSessionContext(options.preserveAttachedBrowserSession === true, () => runAgentBrowserToolInContext(options));
|
|
13
|
+
const details = isRecord(result.details) ? result.details : undefined;
|
|
14
|
+
const sessionKey = getSessionContextKey(typeof details?.sessionName === "string" ? details.sessionName : undefined, typeof details?.namespace === "string" ? details.namespace : undefined);
|
|
15
|
+
const page = options.state.sessionPageState.get(sessionKey);
|
|
16
|
+
return page.tabReopenPending === undefined ? result : {
|
|
17
|
+
...result,
|
|
18
|
+
details: { ...details, sessionTabReopenPending: page.tabReopenPending, ...(page.refSnapshotInvalidation ? { refSnapshotInvalidation: page.refSnapshotInvalidation } : {}) },
|
|
19
|
+
};
|
|
12
20
|
}
|
|
13
21
|
async function runAgentBrowserToolInContext(options) {
|
|
14
22
|
const preparedResult = await prepareBrowserRun(options);
|
|
@@ -34,7 +42,6 @@ async function runAgentBrowserToolInContext(options) {
|
|
|
34
42
|
signal: options.signal,
|
|
35
43
|
stdin: prepared.processStdin,
|
|
36
44
|
timeoutMs: prepared.processTimeoutMs,
|
|
37
|
-
trustedFirstBatchTabSelection: prepared.pinnedBatchUnwrapMode !== undefined,
|
|
38
45
|
});
|
|
39
46
|
const missingBinaryResult = await buildMissingBinaryFailureResult({
|
|
40
47
|
compatibilityWorkaround: prepared.compatibilityWorkaround,
|
package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js
CHANGED
|
@@ -100,6 +100,9 @@ export async function acquireOwnedManagedSessionDaemonPolicy(options) {
|
|
|
100
100
|
context.restoreState.recordDaemonRestoreKey(context.sessionName, context.namespace, daemon.restoreKey);
|
|
101
101
|
return !["inactive", "missing-binary"].includes(daemon.status) && !activePolicyMatches
|
|
102
102
|
? {
|
|
103
|
+
cleanupOnlyReason: daemon.status === "active" && restoreDisabledPolicyNeedsProvenance && !hasKnownDaemonRestoreKey
|
|
104
|
+
? "restore-disabled-daemon-without-provenance"
|
|
105
|
+
: undefined,
|
|
103
106
|
daemonStatus: daemon.status,
|
|
104
107
|
error: [
|
|
105
108
|
"This wrapper-owned session's live daemon does not match the requested managed-restore policy.",
|
package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js
CHANGED
|
@@ -25,7 +25,7 @@ function findCommandTimeoutMs(commandTokens) {
|
|
|
25
25
|
const firstWaitArgument = commandTokens[0] === "wait" ? commandTokens[1] : undefined;
|
|
26
26
|
return firstWaitArgument && !firstWaitArgument.startsWith("-") ? parseMillisecondsToken(firstWaitArgument) : undefined;
|
|
27
27
|
}
|
|
28
|
-
function findFirstPositionalArgument(commandTokens) {
|
|
28
|
+
export function findFirstPositionalArgument(commandTokens) {
|
|
29
29
|
for (let index = 1; index < commandTokens.length; index += 1) {
|
|
30
30
|
const token = commandTokens[index];
|
|
31
31
|
const flag = token.split("=", 1)[0];
|
|
@@ -16,13 +16,13 @@ import { buildAgentBrowserResultCategoryDetails } from "../../results/categories
|
|
|
16
16
|
import { applyNamespaceToNextActions } from "../../results/next-actions.js";
|
|
17
17
|
import { buildSessionAwareStaleRefNextActions, buildSessionTabRecoveryNextActions } from "../../results/recovery-next-actions.js";
|
|
18
18
|
import { resolveVisibleRefActionFromSnapshot } from "../../results/selector-recovery.js";
|
|
19
|
-
import { extractRefSnapshotFromData } from "../../session-page-state.js";
|
|
20
|
-
import { buildExecutionPlan, canUseHeadlessCompatibilityUserAgent, createFreshSessionName, extractCommandTokens, extractUpstreamCommandTokens, getDefaultHeadlessCompatUserAgent, parseWaitCommandTokens, redactInvocationArgs, } from "../../runtime.js";
|
|
19
|
+
import { buildPageTransitionRefSnapshotInvalidation, extractRefSnapshotFromData, normalizeComparableUrl } from "../../session-page-state.js";
|
|
20
|
+
import { buildExecutionPlan, canUseHeadlessCompatibilityUserAgent, createFreshSessionName, extractCommandTokens, extractUpstreamCommandTokens, getDefaultHeadlessCompatUserAgent, parseWaitCommandTokens, redactInvocationArgs, redactSensitiveText, } from "../../runtime.js";
|
|
21
21
|
import { buildOwnedManagedSessionRestoreContext, resolveExplicitAutosaveInterval, withOwnedManagedSessionContext, } from "../../managed-session-restore.js";
|
|
22
22
|
import { getAgentBrowserProcessEnvironment } from "../../process-environment.js";
|
|
23
23
|
import { getExplicitSessionPageVerificationRequirement, getPageTargetValidationError, } from "../../page-target-validation.js";
|
|
24
24
|
import { acquireOwnedManagedSessionDaemonPolicy, getRunningHeadedAutosavePolicyChangeError } from "./managed-session-daemon-policy.js";
|
|
25
|
-
import {
|
|
25
|
+
import { buildManagedSessionOutcome, buildSessionDetailFields, buildStaleRefPreflight, getSessionContextKey, extractStringResultField, ensureSessionTabTarget, getGuardedRefUsage, getTraceOwnerGuardMessage, runSessionCommandData, shouldPinSessionTabForCommand, } from "./session-state.js";
|
|
26
26
|
import { getUpstreamEffectiveBatchSteps, parseBatchStdinJsonArray } from "../batch-stdin.js";
|
|
27
27
|
import { buildElectronHostFailureResult, formatAgentBrowserNextActionsText, getElectronLaunchFailureCategory, redactRecoveryHint } from "./final-result.js";
|
|
28
28
|
import { prepareClickDispatchProbe } from "./click-dispatch.js";
|
|
@@ -241,8 +241,8 @@ function getSamePageFreshnessPreflightFailure(options) {
|
|
|
241
241
|
const { refIds } = options;
|
|
242
242
|
if (refIds.length === 0)
|
|
243
243
|
return undefined;
|
|
244
|
-
const previousUrl = options.previousSnapshot.target?.url;
|
|
245
|
-
const currentUrl = options.currentSnapshot.target?.url;
|
|
244
|
+
const previousUrl = normalizeComparableUrl(options.previousSnapshot.target?.url);
|
|
245
|
+
const currentUrl = normalizeComparableUrl(options.currentSnapshot.target?.url);
|
|
246
246
|
if (!previousUrl || !currentUrl || previousUrl !== currentUrl || currentUrl === "about:blank")
|
|
247
247
|
return undefined;
|
|
248
248
|
const mismatchedRefs = refIds.filter((refId) => {
|
|
@@ -267,8 +267,8 @@ async function collectSamePageRefFreshnessPreflight(options) {
|
|
|
267
267
|
const refIds = [...new Set(getGuardedRefUsage(options.commandTokens, options.stdin))];
|
|
268
268
|
if (!options.previousSnapshot || !options.sessionName || refIds.length === 0)
|
|
269
269
|
return undefined;
|
|
270
|
-
const previousUrl = options.previousSnapshot.target?.url;
|
|
271
|
-
const currentTargetUrl = options.currentTarget?.url;
|
|
270
|
+
const previousUrl = normalizeComparableUrl(options.previousSnapshot.target?.url);
|
|
271
|
+
const currentTargetUrl = normalizeComparableUrl(options.currentTarget?.url);
|
|
272
272
|
if (currentTargetUrl === "about:blank" || (previousUrl && currentTargetUrl && previousUrl !== currentTargetUrl))
|
|
273
273
|
return undefined;
|
|
274
274
|
const snapshotData = await runSessionCommandData({ args: ["snapshot", "-i"], cwd: options.cwd, namespace: options.namespace, sessionName: options.sessionName, signal: options.signal });
|
|
@@ -401,7 +401,29 @@ export async function prepareBrowserRun(options) {
|
|
|
401
401
|
let managedSessionPolicyLockTransferred = false;
|
|
402
402
|
let electronLaunchTransferred = false;
|
|
403
403
|
try {
|
|
404
|
-
|
|
404
|
+
let preparedArgs;
|
|
405
|
+
try {
|
|
406
|
+
preparedArgs = await prepareAgentBrowserArgs(runtimeToolArgs, runtimeToolStdin, cwd);
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
signal?.throwIfAborted();
|
|
410
|
+
if (!(error instanceof Error) || !("syscall" in error) || error.syscall !== "mkdir" || !("path" in error) || typeof error.path !== "string")
|
|
411
|
+
throw error;
|
|
412
|
+
const guidance = "Choose a writable artifact path whose parent components are directories. Use absolute paths in raw batch artifact rows.";
|
|
413
|
+
const validationError = redactSensitiveText(`Could not prepare artifact directory ${error.path}: ${error.message}. ${guidance}`);
|
|
414
|
+
const nextActions = [{ artifactPath: redactSensitiveText(error.path), id: "verify-artifact-path", reason: guidance, safety: "The requested browser command did not run; inspect the directory with host file tools before retrying.", tool: "agent_browser" }];
|
|
415
|
+
return { kind: "early-result", result: {
|
|
416
|
+
content: [{ type: "text", text: validationError }],
|
|
417
|
+
details: {
|
|
418
|
+
agentBrowserStarted: false,
|
|
419
|
+
args: redactedArgs,
|
|
420
|
+
nextActions,
|
|
421
|
+
...buildAgentBrowserResultCategoryDetails({ args: redactedArgs, succeeded: false, validationError }),
|
|
422
|
+
validationError,
|
|
423
|
+
},
|
|
424
|
+
isError: true,
|
|
425
|
+
} };
|
|
426
|
+
}
|
|
405
427
|
const userRequestedJson = runtimeToolArgs.includes("--json");
|
|
406
428
|
let executionPlan = buildExecutionPlan(preparedArgs.args, {
|
|
407
429
|
freshSessionName,
|
|
@@ -480,6 +502,8 @@ export async function prepareBrowserRun(options) {
|
|
|
480
502
|
compatibilityUserAgent: compatibilityUserAgentApplied ? compatibilityUserAgent : undefined,
|
|
481
503
|
wrapperInjectedUserAgent: compatibilityUserAgentApplied,
|
|
482
504
|
});
|
|
505
|
+
let managedSessionDaemonInactive = false;
|
|
506
|
+
let managedSessionCleanupOnlyReason;
|
|
483
507
|
if (!executionPlan.validationError && ownedManagedSession) {
|
|
484
508
|
const closeCommand = isCloseCommand(executionPlan.commandInfo.command);
|
|
485
509
|
const policy = await acquireOwnedManagedSessionDaemonPolicy({
|
|
@@ -488,7 +512,9 @@ export async function prepareBrowserRun(options) {
|
|
|
488
512
|
signal,
|
|
489
513
|
});
|
|
490
514
|
managedSessionPolicyLock = policy.lock;
|
|
515
|
+
managedSessionDaemonInactive = policy.daemonStatus === "inactive";
|
|
491
516
|
if (policy.error) {
|
|
517
|
+
managedSessionCleanupOnlyReason = policy.cleanupOnlyReason;
|
|
492
518
|
executionPlan = {
|
|
493
519
|
...executionPlan,
|
|
494
520
|
recoveryHint: undefined,
|
|
@@ -524,10 +550,68 @@ export async function prepareBrowserRun(options) {
|
|
|
524
550
|
let priorSessionTabTarget = priorSessionPageState.tabTarget;
|
|
525
551
|
let priorSessionTabTargetUnknown = priorSessionPageState.tabTargetUnknown;
|
|
526
552
|
const sessionTabPinningReason = priorSessionPageState.pinningReason;
|
|
527
|
-
|
|
528
|
-
|
|
553
|
+
let priorRefSnapshotState = priorSessionPageState.refSnapshot;
|
|
554
|
+
let priorRefSnapshotInvalidation = priorSessionPageState.refSnapshotInvalidation;
|
|
555
|
+
const coldManagedSession = (managedSessionDaemonInactive || priorSessionPageState.tabReopenPending === true)
|
|
556
|
+
&& recordedOwnedSession !== undefined
|
|
557
|
+
&& sessionTabPinningReason === "restore"
|
|
558
|
+
&& ownedManagedSession?.restoreDecision === "enabled"
|
|
559
|
+
&& !managedSessionRestoreDisabled()
|
|
560
|
+
&& !options.preserveAttachedBrowserSession;
|
|
561
|
+
if (coldManagedSession && sessionStateKey) {
|
|
562
|
+
sessionPageState.setTabReopenPending({ pending: true, sessionName: sessionStateKey, update: options.sessionPageStateUpdate });
|
|
563
|
+
priorRefSnapshotState = undefined;
|
|
564
|
+
priorRefSnapshotInvalidation = buildPageTransitionRefSnapshotInvalidation("The managed browser shut down. Reopening its URL reloads the page; run snapshot -i before using page-scoped refs.");
|
|
565
|
+
sessionPageState.applyRefSnapshotInvalidation({ invalidation: priorRefSnapshotInvalidation, sessionName: sessionStateKey, update: options.sessionPageStateUpdate });
|
|
566
|
+
}
|
|
529
567
|
let semanticActionVisibleRefResolution;
|
|
530
568
|
let livePageVerified = false;
|
|
569
|
+
let sessionTabCorrection;
|
|
570
|
+
let sessionTabSelectionError;
|
|
571
|
+
const plannedCommandTokens = extractUpstreamCommandTokens(preparedArgs.args);
|
|
572
|
+
const knownStaleRef = buildStaleRefPreflight({ commandTokens: plannedCommandTokens, currentTarget: priorSessionTabTarget, refSnapshot: priorRefSnapshotState, refSnapshotInvalidation: priorRefSnapshotInvalidation, stdin: runtimeToolStdin });
|
|
573
|
+
const invalidStdin = validateStdinCommandContract({ command: executionPlan.commandInfo.command, commandTokens: plannedCommandTokens, stdin: runtimeToolStdin });
|
|
574
|
+
const pinSessionTab = shouldPinSessionTabForCommand({
|
|
575
|
+
command: executionPlan.commandInfo.command,
|
|
576
|
+
commandTokens: plannedCommandTokens,
|
|
577
|
+
// URL QA clears diagnostics before its explicit open; those clears do not need the old tab.
|
|
578
|
+
pinningRequired: sessionTabPinningReason !== undefined && compiledQaPreset?.checks.url === undefined,
|
|
579
|
+
reopenPending: coldManagedSession,
|
|
580
|
+
sessionName: executionPlan.sessionName,
|
|
581
|
+
stdin: runtimeToolStdin,
|
|
582
|
+
});
|
|
583
|
+
if (!executionPlan.validationError && !executionPlan.plainTextInspection && !knownStaleRef && !invalidStdin && priorSessionTabTarget && pinSessionTab) {
|
|
584
|
+
signal?.throwIfAborted();
|
|
585
|
+
const reopened = !coldManagedSession || await runSessionCommandData({
|
|
586
|
+
args: ["open", priorSessionTabTarget.url], cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal, timeoutMs: params.timeoutMs,
|
|
587
|
+
onProcessResult: ({ agentBrowserStarted }) => {
|
|
588
|
+
// A started open may have navigated even if its CLI was aborted before replying.
|
|
589
|
+
if (agentBrowserStarted && sessionStateKey)
|
|
590
|
+
sessionPageState.setTabReopenPending({ pending: false, sessionName: sessionStateKey, update: options.sessionPageStateUpdate });
|
|
591
|
+
},
|
|
592
|
+
}) !== undefined;
|
|
593
|
+
const selection = signal?.aborted ? undefined : reopened
|
|
594
|
+
? await ensureSessionTabTarget({ cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal, target: priorSessionTabTarget })
|
|
595
|
+
: { error: "agent-browser could not reopen the remembered URL after the managed browser shut down. Navigate explicitly, then run snapshot -i before retrying." };
|
|
596
|
+
if (coldManagedSession && signal?.aborted) {
|
|
597
|
+
const errorText = "agent_browser was aborted while reopening the remembered page. The requested command did not run.";
|
|
598
|
+
return { kind: "early-result", result: {
|
|
599
|
+
content: [{ type: "text", text: errorText }],
|
|
600
|
+
details: {
|
|
601
|
+
aborted: true, args: redactedArgs, command: executionPlan.commandInfo.command,
|
|
602
|
+
effectiveArgs: redactInvocationArgs(executionPlan.effectiveArgs), sessionMode,
|
|
603
|
+
...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
|
|
604
|
+
...buildAgentBrowserResultCategoryDetails({ args: redactedArgs, command: executionPlan.commandInfo.command, errorText, failureCategory: "aborted", succeeded: false }),
|
|
605
|
+
},
|
|
606
|
+
isError: true,
|
|
607
|
+
} };
|
|
608
|
+
}
|
|
609
|
+
signal?.throwIfAborted();
|
|
610
|
+
sessionTabCorrection = selection?.correction;
|
|
611
|
+
sessionTabSelectionError = selection?.error;
|
|
612
|
+
if (selection?.error)
|
|
613
|
+
executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: selection.error };
|
|
614
|
+
}
|
|
531
615
|
const isCallerOwnedExplicitSession = () => executionPlan.sessionName !== undefined
|
|
532
616
|
&& executionPlan.usedImplicitSession === false
|
|
533
617
|
&& ownedManagedSession === undefined;
|
|
@@ -655,7 +739,7 @@ export async function prepareBrowserRun(options) {
|
|
|
655
739
|
freshSessionOrdinal += 1;
|
|
656
740
|
}
|
|
657
741
|
if (executionPlan.validationError) {
|
|
658
|
-
const nextActions = applyNamespaceToNextActions(unsupportedScrollIntoViewRecovery?.nextActions, executionPlan.namespace);
|
|
742
|
+
const nextActions = applyNamespaceToNextActions(sessionTabSelectionError ? buildSessionTabRecoveryNextActions({ kind: "tab-drift", resultCategory: "failure", sessionName: executionPlan.sessionName, tabCorrection: sessionTabCorrection, target: priorSessionTabTarget }) : unsupportedScrollIntoViewRecovery?.nextActions, executionPlan.namespace);
|
|
659
743
|
const nextActionsText = formatAgentBrowserNextActionsText(nextActions);
|
|
660
744
|
return { kind: "early-result", statePatch, result: {
|
|
661
745
|
content: [{ type: "text", text: [executionPlan.validationError, nextActionsText].filter((text) => text !== undefined).join("\n\n") }],
|
|
@@ -667,11 +751,16 @@ export async function prepareBrowserRun(options) {
|
|
|
667
751
|
compiledSourceLookup: redactedCompiledSourceLookup,
|
|
668
752
|
compiledNetworkSourceLookup: redactedCompiledNetworkSourceLookup,
|
|
669
753
|
invalidValueFlag: executionPlan.invalidValueFlag,
|
|
754
|
+
managedSessionCleanupOnlyReason,
|
|
755
|
+
...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
|
|
756
|
+
...(managedSessionCleanupOnlyReason ? { namespace: ownedManagedSession?.namespace ?? "" } : {}),
|
|
670
757
|
nextActions,
|
|
671
758
|
sessionMode,
|
|
672
759
|
sessionRecoveryHint: redactedRecoveryHint,
|
|
673
760
|
startupScopedFlags: executionPlan.startupScopedFlags,
|
|
674
|
-
...
|
|
761
|
+
...(sessionTabSelectionError ? { effectiveArgs: redactedEffectiveArgs, sessionTabCorrection } : {}),
|
|
762
|
+
...(coldManagedSession ? { refSnapshotInvalidation: priorRefSnapshotInvalidation } : {}),
|
|
763
|
+
...buildAgentBrowserResultCategoryDetails({ args: redactedArgs, command: executionPlan.commandInfo.command, errorText: executionPlan.validationError, failureCategory: sessionTabSelectionError ? "tab-drift" : undefined, succeeded: false, validationError: executionPlan.validationError }),
|
|
675
764
|
validationError: executionPlan.validationError,
|
|
676
765
|
},
|
|
677
766
|
isError: true,
|
|
@@ -911,109 +1000,9 @@ export async function prepareBrowserRun(options) {
|
|
|
911
1000
|
});
|
|
912
1001
|
if (directAnchorDownload)
|
|
913
1002
|
return { kind: "early-result", statePatch: { ...statePatch, artifactManifest: directAnchorDownload.artifactManifest ?? statePatch.artifactManifest }, result: directAnchorDownload.result };
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
let processArgs = executionPlan.effectiveArgs;
|
|
918
|
-
let processStdin = preparedArgs.stdin ?? runtimeToolStdin;
|
|
919
|
-
if (priorSessionTabTarget &&
|
|
920
|
-
shouldPinSessionTabForCommand({
|
|
921
|
-
command: executionPlan.commandInfo.command,
|
|
922
|
-
commandTokens,
|
|
923
|
-
pinningRequired: sessionTabPinningReason !== undefined,
|
|
924
|
-
sessionName: executionPlan.sessionName,
|
|
925
|
-
stdin: runtimeToolStdin,
|
|
926
|
-
})) {
|
|
927
|
-
const collectTabSelection = promptRefSnapshot && getGuardedRefUsage(commandTokens, runtimeToolStdin).length > 0 ? collectAnySessionTabSelection : collectSessionTabSelection;
|
|
928
|
-
const plannedSessionTabSelection = await collectTabSelection({
|
|
929
|
-
cwd,
|
|
930
|
-
namespace: executionPlan.namespace,
|
|
931
|
-
sessionName: executionPlan.sessionName,
|
|
932
|
-
signal,
|
|
933
|
-
target: priorSessionTabTarget,
|
|
934
|
-
});
|
|
935
|
-
if (plannedSessionTabSelection && executionPlan.sessionName) {
|
|
936
|
-
if (executionPlan.commandInfo.command === "eval" && runtimeToolStdin !== undefined) {
|
|
937
|
-
const appliedSessionTabSelection = await applyOpenResultTabCorrection({
|
|
938
|
-
correction: plannedSessionTabSelection,
|
|
939
|
-
cwd,
|
|
940
|
-
namespace: executionPlan.namespace,
|
|
941
|
-
sessionName: executionPlan.sessionName,
|
|
942
|
-
signal,
|
|
943
|
-
});
|
|
944
|
-
if (!appliedSessionTabSelection) {
|
|
945
|
-
const error = "agent-browser could not re-select the intended tab before running the command.";
|
|
946
|
-
return { kind: "early-result", statePatch, result: {
|
|
947
|
-
content: [{ type: "text", text: error }],
|
|
948
|
-
details: {
|
|
949
|
-
args: redactedArgs,
|
|
950
|
-
command: executionPlan.commandInfo.command,
|
|
951
|
-
compatibilityWorkaround,
|
|
952
|
-
effectiveArgs: redactedEffectiveArgs,
|
|
953
|
-
sessionMode,
|
|
954
|
-
sessionTabCorrection: plannedSessionTabSelection,
|
|
955
|
-
...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: error, failureCategory: "tab-drift", succeeded: false, tabDrift: true, validationError: error }),
|
|
956
|
-
nextActions: applyNamespaceToNextActions(buildSessionTabRecoveryNextActions({
|
|
957
|
-
kind: "tab-drift",
|
|
958
|
-
resultCategory: "failure",
|
|
959
|
-
sessionName: executionPlan.sessionName,
|
|
960
|
-
tabCorrection: plannedSessionTabSelection,
|
|
961
|
-
target: priorSessionTabTarget,
|
|
962
|
-
}), executionPlan.namespace),
|
|
963
|
-
validationError: error,
|
|
964
|
-
...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
|
|
965
|
-
},
|
|
966
|
-
isError: true,
|
|
967
|
-
} };
|
|
968
|
-
}
|
|
969
|
-
sessionTabCorrection = appliedSessionTabSelection;
|
|
970
|
-
}
|
|
971
|
-
else {
|
|
972
|
-
const pinnedBatchPlan = buildPinnedBatchPlan({
|
|
973
|
-
command: executionPlan.commandInfo.command,
|
|
974
|
-
commandTokens,
|
|
975
|
-
selectedTab: plannedSessionTabSelection.selectedTab,
|
|
976
|
-
stdin: runtimeToolStdin,
|
|
977
|
-
});
|
|
978
|
-
if (pinnedBatchPlan && "error" in pinnedBatchPlan) {
|
|
979
|
-
return { kind: "early-result", statePatch, result: {
|
|
980
|
-
content: [{ type: "text", text: pinnedBatchPlan.error }],
|
|
981
|
-
details: {
|
|
982
|
-
args: redactedArgs,
|
|
983
|
-
command: executionPlan.commandInfo.command,
|
|
984
|
-
compatibilityWorkaround,
|
|
985
|
-
effectiveArgs: redactedEffectiveArgs,
|
|
986
|
-
sessionMode,
|
|
987
|
-
sessionTabCorrection: plannedSessionTabSelection,
|
|
988
|
-
...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: pinnedBatchPlan.error, failureCategory: "tab-drift", succeeded: false, tabDrift: true, validationError: pinnedBatchPlan.error }),
|
|
989
|
-
nextActions: applyNamespaceToNextActions(buildSessionTabRecoveryNextActions({
|
|
990
|
-
kind: "tab-drift",
|
|
991
|
-
resultCategory: "failure",
|
|
992
|
-
sessionName: executionPlan.sessionName,
|
|
993
|
-
tabCorrection: plannedSessionTabSelection,
|
|
994
|
-
target: priorSessionTabTarget,
|
|
995
|
-
}), executionPlan.namespace),
|
|
996
|
-
validationError: pinnedBatchPlan.error,
|
|
997
|
-
...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
|
|
998
|
-
},
|
|
999
|
-
isError: true,
|
|
1000
|
-
} };
|
|
1001
|
-
}
|
|
1002
|
-
if (pinnedBatchPlan) {
|
|
1003
|
-
sessionTabCorrection = plannedSessionTabSelection;
|
|
1004
|
-
// The rewritten batch must keep the caller's fail-fast semantics:
|
|
1005
|
-
// upstream reads only the exact --bail token, so re-emit it whenever
|
|
1006
|
-
// the original batch tokens carried it (argv or stdin/job/qa mode).
|
|
1007
|
-
const pinnedBailArgs = commandTokens.includes("--bail") ? ["--bail"] : [];
|
|
1008
|
-
processArgs = ["--json", ...(executionPlan.namespace !== undefined ? ["--namespace", executionPlan.namespace] : []), "--session", executionPlan.sessionName, "batch", ...pinnedBailArgs];
|
|
1009
|
-
processStdin = JSON.stringify(pinnedBatchPlan.steps);
|
|
1010
|
-
includePinnedNavigationSummary = pinnedBatchPlan.includeNavigationSummary;
|
|
1011
|
-
pinnedBatchUnwrapMode = pinnedBatchPlan.unwrapMode;
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
const clickDispatchProbe = pinnedBatchUnwrapMode === undefined && compiledElectron === undefined
|
|
1003
|
+
const processArgs = executionPlan.effectiveArgs;
|
|
1004
|
+
const processStdin = preparedArgs.stdin ?? runtimeToolStdin;
|
|
1005
|
+
const clickDispatchProbe = compiledElectron === undefined
|
|
1017
1006
|
? await prepareClickDispatchProbe({ commandTokens, cwd, namespace: executionPlan.namespace, refSnapshot: promptRefSnapshot, sessionName: executionPlan.sessionName, signal })
|
|
1018
1007
|
: undefined;
|
|
1019
1008
|
let readTimeoutPageUrl = priorSessionTabTarget?.url;
|
|
@@ -1061,9 +1050,7 @@ export async function prepareBrowserRun(options) {
|
|
|
1061
1050
|
electronLaunch,
|
|
1062
1051
|
exactSensitiveValues,
|
|
1063
1052
|
executionPlan,
|
|
1064
|
-
includePinnedNavigationSummary,
|
|
1065
1053
|
ownedManagedSessionContext: ownedManagedSession,
|
|
1066
|
-
pinnedBatchUnwrapMode,
|
|
1067
1054
|
preparedArgs,
|
|
1068
1055
|
priorRefSnapshotState,
|
|
1069
1056
|
priorSessionTabTarget,
|