pi-agent-browser-native 0.9.2 → 0.9.3
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 +14 -0
- package/README.md +18 -6
- package/dist/extensions/agent-browser/index.js +39 -16
- package/dist/extensions/agent-browser/lib/batch-lifecycle.js +6 -3
- package/dist/extensions/agent-browser/lib/browser-transcript.js +2 -1
- package/dist/extensions/agent-browser/lib/native-output.js +2 -1
- package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +2 -8
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +12 -2
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +58 -7
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +18 -12
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +33 -24
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +111 -53
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +32 -20
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +37 -32
- package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +26 -8
- package/dist/extensions/agent-browser/lib/orchestration/output-file.js +3 -1
- package/dist/extensions/agent-browser/lib/page-target-validation.js +10 -3
- package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +2 -1
- package/dist/extensions/agent-browser/lib/playbook.js +2 -2
- package/dist/extensions/agent-browser/lib/process-environment.js +12 -3
- package/dist/extensions/agent-browser/lib/process.js +6 -6
- package/dist/extensions/agent-browser/lib/read-confirmation.js +56 -16
- package/dist/extensions/agent-browser/lib/results/confirmation.js +3 -0
- package/dist/extensions/agent-browser/lib/results/envelope.js +5 -1
- package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +3 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +34 -1
- package/dist/extensions/agent-browser/lib/results/presentation/registry.js +5 -1
- package/dist/extensions/agent-browser/lib/results/presentation.js +15 -2
- package/dist/extensions/agent-browser/lib/results/selector-recovery.js +5 -5
- package/dist/extensions/agent-browser/lib/runtime.js +5 -1
- package/dist/extensions/agent-browser/lib/session-page-state.js +35 -16
- package/docs/ARCHITECTURE.md +5 -5
- package/docs/COMMAND_REFERENCE.md +13 -9
- package/docs/RELEASE.md +6 -5
- package/docs/REQUIREMENTS.md +1 -0
- package/docs/SESSION_STORAGE.md +1 -1
- package/docs/SUPPORT_MATRIX.md +9 -3
- package/docs/TOOL_CONTRACT.md +20 -14
- package/package.json +4 -4
package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js
CHANGED
|
@@ -9,6 +9,7 @@ import { readProcessStartIdentity } from "../../process-identity.js";
|
|
|
9
9
|
import { getAgentBrowserProcessEnvironment, withAgentBrowserProcessEnvironment } from "../../process-environment.js";
|
|
10
10
|
import { runAgentBrowserProcess, withAttachedBrowserSessionContext } from "../../process.js";
|
|
11
11
|
import { getAgentBrowserErrorText, parseAgentBrowserEnvelope } from "../../results/envelope.js";
|
|
12
|
+
import { detectConfirmationRequired } from "../../results/confirmation.js";
|
|
12
13
|
import { redactInvocationArgs } from "../../runtime.js";
|
|
13
14
|
import { runSessionCommandData } from "./session-state.js";
|
|
14
15
|
const MANAGED_SESSION_DAEMON_INSPECTION_TIMEOUT_MS = 35_000;
|
|
@@ -158,7 +159,7 @@ export async function acquireOwnedManagedSessionDaemonPolicy(options) {
|
|
|
158
159
|
}
|
|
159
160
|
}
|
|
160
161
|
export async function closeManagedSession(options) {
|
|
161
|
-
return withAgentBrowserProcessEnvironment(options.socketDir ? { PI_AGENT_BROWSER_SOCKET_DIR: options.socketDir } : {}, async () => {
|
|
162
|
+
return withAgentBrowserProcessEnvironment({ AGENT_BROWSER_CONFIRM_ACTIONS: options.confirmActions, ...(options.socketDir ? { PI_AGENT_BROWSER_SOCKET_DIR: options.socketDir } : {}) }, async () => {
|
|
162
163
|
const controller = new AbortController();
|
|
163
164
|
let phase = "policy coordination";
|
|
164
165
|
let phaseStartedAt = Date.now();
|
|
@@ -209,28 +210,33 @@ export async function closeManagedSession(options) {
|
|
|
209
210
|
});
|
|
210
211
|
clearTimeout(timer);
|
|
211
212
|
stdoutSpillPath = processResult.stdoutSpillPath;
|
|
213
|
+
const parsed = await parseAgentBrowserEnvelope({ stdout: processResult.stdout, stdoutPath: processResult.stdoutSpillPath });
|
|
212
214
|
if (!processResult.aborted && !processResult.spawnError && processResult.exitCode === 0) {
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
215
|
+
const data = parsed.envelope?.success === true && isRecord(parsed.envelope.data) && parsed.envelope.data.closed === true ? parsed.envelope.data : undefined;
|
|
216
|
+
if (data) {
|
|
217
|
+
options.restoreState.clear(options.sessionName, options.namespace);
|
|
218
|
+
pruneOwnedManagedSessionRestoreSnapshots({
|
|
219
|
+
cwd: options.cwd,
|
|
220
|
+
namespace: options.namespace,
|
|
221
|
+
restoreKey: ownedRestoreKey,
|
|
222
|
+
statePath: typeof data.statePath === "string" ? data.statePath : undefined,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
222
225
|
}
|
|
223
|
-
|
|
226
|
+
const pending = detectConfirmationRequired(parsed.envelope?.data);
|
|
227
|
+
return timeoutError ?? (pending ? `Native close requires confirmation (${pending.id}); the session remains wrapper-owned.` : getAgentBrowserErrorText({
|
|
224
228
|
aborted: processResult.aborted,
|
|
225
229
|
command: "close",
|
|
226
230
|
effectiveArgs: redactInvocationArgs(closeArgs),
|
|
231
|
+
envelope: parsed.envelope,
|
|
227
232
|
exitCode: processResult.exitCode,
|
|
233
|
+
parseError: parsed.parseError,
|
|
228
234
|
plainTextInspection: false,
|
|
229
235
|
spawnError: processResult.spawnError,
|
|
230
236
|
stderr: processResult.stderr,
|
|
231
237
|
timedOut: processResult.timedOut,
|
|
232
238
|
timeoutMs: processResult.timeoutMs,
|
|
233
|
-
});
|
|
239
|
+
}));
|
|
234
240
|
}
|
|
235
241
|
catch (error) {
|
|
236
242
|
return timeoutError ?? (error instanceof Error ? error.message : String(error));
|
|
@@ -15,6 +15,7 @@ import { tryContainerScroll, tryPageScrollTo } from "./prepare/scroll-shims.js";
|
|
|
15
15
|
import { trySnapshotFilter } from "./prepare/snapshot-filter.js";
|
|
16
16
|
import { commandTimeoutNeedsActivePageUrl, getCommandAwareProcessTimeoutMs } from "./prepare/wait-timeouts.js";
|
|
17
17
|
import { getPersistentSessionArtifactStore } from "./session-state.js";
|
|
18
|
+
import { isBrowserIndependentConfirmation, suppressConfirmationPageHelpers } from "../../read-confirmation.js";
|
|
18
19
|
import { buildAgentBrowserResultCategoryDetails } from "../../results/categories.js";
|
|
19
20
|
import { applyNamespaceToNextActions } from "../../results/next-actions.js";
|
|
20
21
|
import { buildSessionAwareStaleRefNextActions, buildSessionTabRecoveryNextActions } from "../../results/recovery-next-actions.js";
|
|
@@ -145,7 +146,7 @@ async function prepareBatchScreenshotPaths(args, stdin, cwd) {
|
|
|
145
146
|
return changed
|
|
146
147
|
? {
|
|
147
148
|
args,
|
|
148
|
-
batchScreenshotPathRequests,
|
|
149
|
+
batchScreenshotPathRequests: parsed.steps.flatMap((step, index) => Array.isArray(step) && step.length === 0 ? [] : [batchScreenshotPathRequests[index]]),
|
|
149
150
|
stdin: JSON.stringify(preparedSteps),
|
|
150
151
|
}
|
|
151
152
|
: undefined;
|
|
@@ -325,19 +326,12 @@ function canResolveSemanticVisibleRef(compiled) {
|
|
|
325
326
|
function requiresResolvedSemanticVisibleRef(compiled) {
|
|
326
327
|
return compiled?.action === "select" && compiled.locator !== undefined;
|
|
327
328
|
}
|
|
328
|
-
function resolveSemanticActionVisibleRefArgsFromSnapshot(compiled, snapshotData) {
|
|
329
|
-
if (!canResolveSemanticVisibleRef(compiled))
|
|
330
|
-
return undefined;
|
|
331
|
-
const resolution = resolveVisibleRefActionFromSnapshot({ allowFill: true, compiledAction: compiled, snapshotData });
|
|
332
|
-
if (!resolution)
|
|
333
|
-
return undefined;
|
|
334
|
-
return { args: [...getCompiledSemanticActionSessionPrefix(compiled), ...resolution.args], snapshot: resolution.snapshot };
|
|
335
|
-
}
|
|
336
329
|
async function resolveSemanticActionVisibleRefArgs(options) {
|
|
337
|
-
if (!options.compiled || !options.sessionName)
|
|
330
|
+
if (!canResolveSemanticVisibleRef(options.compiled) || !options.sessionName)
|
|
338
331
|
return undefined;
|
|
339
|
-
const snapshotData = await runSessionCommandData({ args: ["snapshot", "-i"], cwd: options.cwd, namespace: options.namespace, sessionName: options.sessionName, signal: options.signal });
|
|
340
|
-
|
|
332
|
+
const snapshotData = options.refSnapshot ? undefined : await runSessionCommandData({ args: ["snapshot", "-i"], cwd: options.cwd, namespace: options.namespace, sessionName: options.sessionName, signal: options.signal });
|
|
333
|
+
const resolution = resolveVisibleRefActionFromSnapshot({ allowFill: true, compiledAction: options.compiled, refSnapshot: options.refSnapshot, snapshotData });
|
|
334
|
+
return resolution ? { args: [...getCompiledSemanticActionSessionPrefix(options.compiled), ...resolution.args], snapshot: resolution.snapshot } : undefined;
|
|
341
335
|
}
|
|
342
336
|
export async function prepareBrowserRun(options) {
|
|
343
337
|
const { cwd, onUpdate, params, signal, state } = options;
|
|
@@ -423,9 +417,10 @@ export async function prepareBrowserRun(options) {
|
|
|
423
417
|
isError: true,
|
|
424
418
|
} };
|
|
425
419
|
}
|
|
426
|
-
const userRequestedJson = runtimeToolArgs
|
|
427
|
-
const routedReadConfirmation = state.sessionPageState.findReadConfirmation(preparedArgs.args, resolveAgentBrowserNamespace(preparedArgs.args, agentBrowserProcessEnv.AGENT_BROWSER_NAMESPACE));
|
|
428
|
-
const readConfirmation = routedReadConfirmation
|
|
420
|
+
const userRequestedJson = getBooleanFlagValue(runtimeToolArgs, "--json") === true;
|
|
421
|
+
const routedReadConfirmation = state.sessionPageState.findReadConfirmation(preparedArgs.args, resolveAgentBrowserNamespace(preparedArgs.args, agentBrowserProcessEnv.AGENT_BROWSER_NAMESPACE), runtimeToolStdin);
|
|
422
|
+
const readConfirmation = suppressConfirmationPageHelpers(routedReadConfirmation) ? routedReadConfirmation : undefined;
|
|
423
|
+
const browserIndependentConfirmation = isBrowserIndependentConfirmation(readConfirmation);
|
|
429
424
|
let executionPlan = buildExecutionPlan(preparedArgs.args, {
|
|
430
425
|
freshSessionName,
|
|
431
426
|
managedSessionActive: state.managedSessionActive,
|
|
@@ -434,13 +429,14 @@ export async function prepareBrowserRun(options) {
|
|
|
434
429
|
managedSessionNamespace: state.managedSessionNamespace,
|
|
435
430
|
sessionMode,
|
|
436
431
|
stdin: runtimeToolStdin,
|
|
437
|
-
browserIndependentReadConfirmation:
|
|
432
|
+
browserIndependentReadConfirmation: browserIndependentConfirmation,
|
|
438
433
|
});
|
|
439
|
-
const browserIndependent =
|
|
434
|
+
const browserIndependent = browserIndependentConfirmation || isBrowserIndependentRead(extractUpstreamCommandTokens(preparedArgs.args), runtimeToolStdin)
|
|
440
435
|
|| (executionPlan.commandInfo.command === "session" && executionPlan.commandInfo.subcommand === "info");
|
|
441
436
|
const ownedSessionKey = getSessionContextKey(executionPlan.sessionName, executionPlan.namespace);
|
|
442
437
|
const plannedSessionPageState = sessionPageState.get(ownedSessionKey);
|
|
443
|
-
const pageTargetError = readConfirmation ? undefined : getPageTargetValidationError({
|
|
438
|
+
const pageTargetError = readConfirmation && executionPlan.commandInfo.command !== "batch" ? undefined : getPageTargetValidationError({
|
|
439
|
+
allowFirstBatchConfirmation: readConfirmation !== undefined,
|
|
444
440
|
args: executionPlan.effectiveArgs,
|
|
445
441
|
currentPageUrl: plannedSessionPageState.tabTarget?.url,
|
|
446
442
|
pageUrlUnknown: plannedSessionPageState.tabTargetUnknown === true,
|
|
@@ -571,6 +567,15 @@ export async function prepareBrowserRun(options) {
|
|
|
571
567
|
const sessionTabPinningReason = priorSessionPageState.pinningReason;
|
|
572
568
|
let priorRefSnapshotState = priorSessionPageState.refSnapshot;
|
|
573
569
|
let priorRefSnapshotInvalidation = priorSessionPageState.refSnapshotInvalidation;
|
|
570
|
+
const confirmedCapture = sessionStateKey ? sessionPageState.getReadConfirmation(sessionStateKey) : undefined;
|
|
571
|
+
// ponytail: reuse the approved capture for one call; DOM-only renames after that sample are not resampled on this use.
|
|
572
|
+
const reuseConfirmedCapture = confirmedCapture?.refSnapshotFresh === true;
|
|
573
|
+
if (reuseConfirmedCapture && confirmedCapture) {
|
|
574
|
+
const consumed = { ...confirmedCapture };
|
|
575
|
+
delete consumed.refSnapshotFresh;
|
|
576
|
+
sessionPageState.applyReadConfirmation(consumed, options.sessionPageStateUpdate);
|
|
577
|
+
state.observedBrowserEffects = { ...state.observedBrowserEffects, readConfirmation: consumed };
|
|
578
|
+
}
|
|
574
579
|
let nativeGenerationChanged = false;
|
|
575
580
|
if (!browserIndependent && !isCloseCommand(executionPlan.commandInfo.command) && priorRefSnapshotState?.refIds.length && sessionStateKey && executionPlan.sessionName) {
|
|
576
581
|
const daemon = await inspectManagedSessionDaemon({ cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal, includeGeneration: true, headedManagedAutosaveInterval: ownedManagedSession?.headedManagedAutosaveInterval ?? (ownedManagedSession?.headedManagedAutosaveDisabled ? "0" : undefined), timeoutMs: params.timeoutMs });
|
|
@@ -651,7 +656,7 @@ export async function prepareBrowserRun(options) {
|
|
|
651
656
|
const isCallerOwnedExplicitSession = () => executionPlan.sessionName !== undefined
|
|
652
657
|
&& executionPlan.usedImplicitSession === false
|
|
653
658
|
&& ownedManagedSession === undefined;
|
|
654
|
-
const requiresLivePageVerification = () => !readConfirmation && (isCallerOwnedExplicitSession() || options.preserveAttachedBrowserSession === true);
|
|
659
|
+
const requiresLivePageVerification = () => !readConfirmation && (reuseConfirmedCapture || isCallerOwnedExplicitSession() || options.preserveAttachedBrowserSession === true);
|
|
655
660
|
const verifyLivePage = async (request) => {
|
|
656
661
|
if (!request.requirement || !executionPlan.sessionName)
|
|
657
662
|
return;
|
|
@@ -690,7 +695,9 @@ export async function prepareBrowserRun(options) {
|
|
|
690
695
|
return;
|
|
691
696
|
}
|
|
692
697
|
livePageVerified = true;
|
|
693
|
-
priorSessionTabTarget
|
|
698
|
+
priorSessionTabTarget = priorSessionTabTarget?.url === liveUrl
|
|
699
|
+
? { ...priorSessionTabTarget, url: liveUrl }
|
|
700
|
+
: { url: liveUrl };
|
|
694
701
|
priorSessionTabTargetUnknown = undefined;
|
|
695
702
|
};
|
|
696
703
|
const hasPotentialLiveSemanticSession = state.managedSessionActive || priorSessionTabTarget !== undefined || isCallerOwnedExplicitSession() || options.preserveAttachedBrowserSession === true;
|
|
@@ -706,6 +713,7 @@ export async function prepareBrowserRun(options) {
|
|
|
706
713
|
compiled: compiledSemanticAction,
|
|
707
714
|
cwd,
|
|
708
715
|
namespace: executionPlan.namespace,
|
|
716
|
+
refSnapshot: reuseConfirmedCapture && !priorSessionTabTargetUnknown && !priorRefSnapshotInvalidation ? priorRefSnapshotState : undefined,
|
|
709
717
|
sessionName: executionPlan.sessionName,
|
|
710
718
|
signal,
|
|
711
719
|
});
|
|
@@ -872,6 +880,7 @@ export async function prepareBrowserRun(options) {
|
|
|
872
880
|
const staleRefPreflight = buildStaleRefPreflight({
|
|
873
881
|
commandTokens,
|
|
874
882
|
currentTarget: priorSessionTabTarget,
|
|
883
|
+
requireExactTargetUrl: reuseConfirmedCapture,
|
|
875
884
|
refSnapshot: resolvedSemanticActionRefSnapshot ?? priorRefSnapshotState,
|
|
876
885
|
refSnapshotInvalidation: resolvedSemanticActionRefSnapshot ? undefined : priorRefSnapshotInvalidation,
|
|
877
886
|
stdin: runtimeToolStdin,
|
|
@@ -899,7 +908,7 @@ export async function prepareBrowserRun(options) {
|
|
|
899
908
|
commandTokens,
|
|
900
909
|
cwd,
|
|
901
910
|
currentTarget: priorSessionTabTarget,
|
|
902
|
-
previousSnapshot: resolvedSemanticActionRefSnapshot ? undefined : priorRefSnapshotState,
|
|
911
|
+
previousSnapshot: resolvedSemanticActionRefSnapshot || reuseConfirmedCapture ? undefined : priorRefSnapshotState,
|
|
903
912
|
stdin: runtimeToolStdin,
|
|
904
913
|
namespace: executionPlan.namespace,
|
|
905
914
|
sessionName: executionPlan.sessionName,
|
|
@@ -1032,9 +1041,6 @@ export async function prepareBrowserRun(options) {
|
|
|
1032
1041
|
}
|
|
1033
1042
|
const processArgs = executionPlan.effectiveArgs;
|
|
1034
1043
|
const processStdin = preparedArgs.stdin ?? runtimeToolStdin;
|
|
1035
|
-
const clickDispatchProbe = compiledElectron === undefined
|
|
1036
|
-
? await prepareClickDispatchProbe({ commandTokens, cwd, namespace: executionPlan.namespace, refSnapshot: promptRefSnapshot, sessionName: executionPlan.sessionName, signal })
|
|
1037
|
-
: undefined;
|
|
1038
1044
|
let readTimeoutPageUrl = priorSessionTabTarget?.url;
|
|
1039
1045
|
if (options.params.timeoutMs === undefined && readTimeoutPageUrl === undefined && executionPlan.sessionName && commandTimeoutNeedsActivePageUrl(commandTokens, processStdin)) {
|
|
1040
1046
|
try {
|
|
@@ -1044,6 +1050,9 @@ export async function prepareBrowserRun(options) {
|
|
|
1044
1050
|
catch { }
|
|
1045
1051
|
}
|
|
1046
1052
|
const processTimeoutMs = options.params.timeoutMs ?? getDialogAwareProcessTimeoutMs(commandTokens, promptRefSnapshot, processStdin) ?? getCommandAwareProcessTimeoutMs(commandTokens, processStdin, readTimeoutPageUrl);
|
|
1053
|
+
const clickDispatchProbe = compiledElectron === undefined
|
|
1054
|
+
? await prepareClickDispatchProbe({ commandTokens, cwd, namespace: executionPlan.namespace, refSnapshot: promptRefSnapshot, sessionName: executionPlan.sessionName, signal, timeoutMs: processTimeoutMs })
|
|
1055
|
+
: undefined;
|
|
1047
1056
|
const redactedProcessArgs = redactInvocationArgs(prepareAgentBrowserSpawnArgs(processArgs, ownedManagedSession?.compatibilityUserAgent, options.preserveAttachedBrowserSession, chromeStartupArgs));
|
|
1048
1057
|
const scrollAmount = Number(commandTokens.find((token) => /^\d+(?:\.\d+)?$/.test(token)));
|
|
1049
1058
|
const shouldProbeScrollNoop = executionPlan.commandInfo.command === "scroll" && executionPlan.startupScopedFlags.length === 0 && (state.managedSessionActive || sessionMode === "fresh") && (!Number.isFinite(scrollAmount) || scrollAmount >= 500);
|