pi-agent-browser-native 0.2.48 → 0.2.49
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 +17 -0
- package/README.md +16 -6
- package/dist/extensions/agent-browser/index.js +785 -0
- package/dist/extensions/agent-browser/lib/argv-descriptor.js +71 -0
- package/dist/extensions/agent-browser/lib/argv-grammar.js +121 -0
- package/dist/extensions/agent-browser/lib/bash-guard.js +190 -0
- package/dist/extensions/agent-browser/lib/command-policy.js +85 -0
- package/dist/extensions/agent-browser/lib/command-taxonomy.js +302 -0
- package/dist/extensions/agent-browser/lib/config-policy.js +686 -0
- package/dist/extensions/agent-browser/lib/config.js +122 -0
- package/dist/extensions/agent-browser/lib/electron/cdp.js +51 -0
- package/dist/extensions/agent-browser/lib/electron/cleanup.js +212 -0
- package/dist/extensions/agent-browser/lib/electron/discovery.js +633 -0
- package/dist/extensions/agent-browser/lib/electron/launch.js +351 -0
- package/{extensions/agent-browser/lib/electron/text.ts → dist/extensions/agent-browser/lib/electron/text.js} +5 -5
- package/dist/extensions/agent-browser/lib/executable-path.js +20 -0
- package/dist/extensions/agent-browser/lib/fs-utils.js +18 -0
- package/dist/extensions/agent-browser/lib/input-modes/electron.js +165 -0
- package/dist/extensions/agent-browser/lib/input-modes/job.js +519 -0
- package/dist/extensions/agent-browser/lib/input-modes/lookups.js +440 -0
- package/dist/extensions/agent-browser/lib/input-modes/params.js +164 -0
- package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +119 -0
- package/dist/extensions/agent-browser/lib/input-modes/shared.js +42 -0
- package/dist/extensions/agent-browser/lib/input-modes/types.js +21 -0
- package/dist/extensions/agent-browser/lib/input-modes.js +10 -0
- package/dist/extensions/agent-browser/lib/json-schema.js +58 -0
- package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +59 -0
- package/dist/extensions/agent-browser/lib/navigation-policy.js +83 -0
- package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +62 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +39 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +276 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +909 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +443 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +47 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/direct-anchor-download.js +141 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +108 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +112 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +158 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +54 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +762 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +491 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.js +40 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-artifacts.js +5 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +731 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/types.js +1 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +718 -0
- package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +247 -0
- package/dist/extensions/agent-browser/lib/orchestration/output-file.js +68 -0
- package/{extensions/agent-browser/lib/parsing.ts → dist/extensions/agent-browser/lib/parsing.js} +12 -11
- package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +241 -0
- package/dist/extensions/agent-browser/lib/playbook.js +121 -0
- package/dist/extensions/agent-browser/lib/process.js +448 -0
- package/dist/extensions/agent-browser/lib/prompt-policy.js +91 -0
- package/dist/extensions/agent-browser/lib/results/action-recommendations.js +220 -0
- package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +111 -0
- package/{extensions/agent-browser/lib/results/artifact-state.ts → dist/extensions/agent-browser/lib/results/artifact-state.js} +4 -8
- package/dist/extensions/agent-browser/lib/results/categories.js +76 -0
- package/dist/extensions/agent-browser/lib/results/confirmation.js +63 -0
- package/dist/extensions/agent-browser/lib/results/contracts.js +8 -0
- package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +74 -0
- package/dist/extensions/agent-browser/lib/results/envelope.js +166 -0
- package/dist/extensions/agent-browser/lib/results/network-routes.js +92 -0
- package/dist/extensions/agent-browser/lib/results/network.js +73 -0
- package/dist/extensions/agent-browser/lib/results/next-actions.js +72 -0
- package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +515 -0
- package/dist/extensions/agent-browser/lib/results/presentation/batch.js +397 -0
- package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +55 -0
- package/dist/extensions/agent-browser/lib/results/presentation/common.js +46 -0
- package/dist/extensions/agent-browser/lib/results/presentation/content.js +24 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +960 -0
- package/dist/extensions/agent-browser/lib/results/presentation/errors.js +205 -0
- package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +134 -0
- package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +159 -0
- package/dist/extensions/agent-browser/lib/results/presentation/registry.js +216 -0
- package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +104 -0
- package/dist/extensions/agent-browser/lib/results/presentation/skills.js +152 -0
- package/dist/extensions/agent-browser/lib/results/presentation.js +177 -0
- package/dist/extensions/agent-browser/lib/results/recovery-actions.js +107 -0
- package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +50 -0
- package/dist/extensions/agent-browser/lib/results/selector-recovery.js +225 -0
- package/{extensions/agent-browser/lib/results/shared.ts → dist/extensions/agent-browser/lib/results/shared.js} +0 -1
- package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +208 -0
- package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +78 -0
- package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +331 -0
- package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +40 -0
- package/dist/extensions/agent-browser/lib/results/snapshot.js +264 -0
- package/dist/extensions/agent-browser/lib/results/text.js +40 -0
- package/{extensions/agent-browser/lib/results.ts → dist/extensions/agent-browser/lib/results.js} +2 -32
- package/dist/extensions/agent-browser/lib/runtime.js +816 -0
- package/dist/extensions/agent-browser/lib/session-page-state.js +411 -0
- package/dist/extensions/agent-browser/lib/string-enum-schema.js +13 -0
- package/dist/extensions/agent-browser/lib/temp.js +498 -0
- package/dist/extensions/agent-browser/lib/web-search.js +562 -0
- package/docs/RELEASE.md +22 -11
- package/docs/SUPPORT_MATRIX.md +4 -3
- package/package.json +9 -5
- package/scripts/config.mjs +8 -2
- package/scripts/doctor.mjs +8 -7
- package/extensions/agent-browser/index.ts +0 -961
- package/extensions/agent-browser/lib/argv-descriptor.ts +0 -90
- package/extensions/agent-browser/lib/argv-grammar.ts +0 -128
- package/extensions/agent-browser/lib/bash-guard.ts +0 -205
- package/extensions/agent-browser/lib/command-policy.ts +0 -71
- package/extensions/agent-browser/lib/command-taxonomy.ts +0 -336
- package/extensions/agent-browser/lib/config-policy.js +0 -690
- package/extensions/agent-browser/lib/config.ts +0 -211
- package/extensions/agent-browser/lib/electron/cdp.ts +0 -69
- package/extensions/agent-browser/lib/electron/cleanup.ts +0 -235
- package/extensions/agent-browser/lib/electron/discovery.ts +0 -710
- package/extensions/agent-browser/lib/electron/launch.ts +0 -499
- package/extensions/agent-browser/lib/executable-path.ts +0 -19
- package/extensions/agent-browser/lib/fs-utils.ts +0 -18
- package/extensions/agent-browser/lib/input-modes/electron.ts +0 -170
- package/extensions/agent-browser/lib/input-modes/job.ts +0 -527
- package/extensions/agent-browser/lib/input-modes/lookups.ts +0 -447
- package/extensions/agent-browser/lib/input-modes/params.ts +0 -205
- package/extensions/agent-browser/lib/input-modes/semantic-action.ts +0 -127
- package/extensions/agent-browser/lib/input-modes/shared.ts +0 -46
- package/extensions/agent-browser/lib/input-modes/types.ts +0 -225
- package/extensions/agent-browser/lib/input-modes.ts +0 -45
- package/extensions/agent-browser/lib/json-schema.ts +0 -73
- package/extensions/agent-browser/lib/launch-scoped-flags.ts +0 -67
- package/extensions/agent-browser/lib/navigation-policy.ts +0 -95
- package/extensions/agent-browser/lib/orchestration/batch-stdin.ts +0 -65
- package/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.ts +0 -44
- package/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.ts +0 -280
- package/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.ts +0 -914
- package/extensions/agent-browser/lib/orchestration/browser-run/final-result.ts +0 -521
- package/extensions/agent-browser/lib/orchestration/browser-run/index.ts +0 -53
- package/extensions/agent-browser/lib/orchestration/browser-run/prepare/direct-anchor-download.ts +0 -158
- package/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.ts +0 -116
- package/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.ts +0 -147
- package/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.ts +0 -183
- package/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.ts +0 -58
- package/extensions/agent-browser/lib/orchestration/browser-run/prepare.ts +0 -847
- package/extensions/agent-browser/lib/orchestration/browser-run/process-output.ts +0 -559
- package/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.ts +0 -47
- package/extensions/agent-browser/lib/orchestration/browser-run/session-artifacts.ts +0 -8
- package/extensions/agent-browser/lib/orchestration/browser-run/session-state.ts +0 -868
- package/extensions/agent-browser/lib/orchestration/browser-run/types.ts +0 -565
- package/extensions/agent-browser/lib/orchestration/electron-host/index.ts +0 -855
- package/extensions/agent-browser/lib/orchestration/input-plan.ts +0 -375
- package/extensions/agent-browser/lib/orchestration/output-file.ts +0 -86
- package/extensions/agent-browser/lib/pi-tool-rendering.ts +0 -267
- package/extensions/agent-browser/lib/playbook.ts +0 -142
- package/extensions/agent-browser/lib/process.ts +0 -516
- package/extensions/agent-browser/lib/prompt-policy.ts +0 -105
- package/extensions/agent-browser/lib/results/action-recommendations.ts +0 -264
- package/extensions/agent-browser/lib/results/artifact-manifest.ts +0 -111
- package/extensions/agent-browser/lib/results/categories.ts +0 -106
- package/extensions/agent-browser/lib/results/confirmation.ts +0 -76
- package/extensions/agent-browser/lib/results/contracts.ts +0 -241
- package/extensions/agent-browser/lib/results/editable-ref-evidence.ts +0 -72
- package/extensions/agent-browser/lib/results/envelope.ts +0 -195
- package/extensions/agent-browser/lib/results/network-routes.ts +0 -83
- package/extensions/agent-browser/lib/results/network.ts +0 -78
- package/extensions/agent-browser/lib/results/next-actions.ts +0 -117
- package/extensions/agent-browser/lib/results/presentation/artifacts.ts +0 -588
- package/extensions/agent-browser/lib/results/presentation/batch.ts +0 -450
- package/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.ts +0 -67
- package/extensions/agent-browser/lib/results/presentation/common.ts +0 -53
- package/extensions/agent-browser/lib/results/presentation/content.ts +0 -36
- package/extensions/agent-browser/lib/results/presentation/diagnostics.ts +0 -923
- package/extensions/agent-browser/lib/results/presentation/errors.ts +0 -227
- package/extensions/agent-browser/lib/results/presentation/large-output.ts +0 -182
- package/extensions/agent-browser/lib/results/presentation/navigation.ts +0 -184
- package/extensions/agent-browser/lib/results/presentation/registry.ts +0 -242
- package/extensions/agent-browser/lib/results/presentation/semantic-action.ts +0 -131
- package/extensions/agent-browser/lib/results/presentation/skills.ts +0 -143
- package/extensions/agent-browser/lib/results/presentation.ts +0 -257
- package/extensions/agent-browser/lib/results/recovery-actions.ts +0 -139
- package/extensions/agent-browser/lib/results/recovery-next-actions.ts +0 -71
- package/extensions/agent-browser/lib/results/selector-recovery.ts +0 -320
- package/extensions/agent-browser/lib/results/snapshot-high-value-controls.ts +0 -273
- package/extensions/agent-browser/lib/results/snapshot-refs.ts +0 -100
- package/extensions/agent-browser/lib/results/snapshot-segments.ts +0 -366
- package/extensions/agent-browser/lib/results/snapshot-spill.ts +0 -63
- package/extensions/agent-browser/lib/results/snapshot.ts +0 -329
- package/extensions/agent-browser/lib/results/text.ts +0 -40
- package/extensions/agent-browser/lib/runtime.ts +0 -988
- package/extensions/agent-browser/lib/session-page-state.ts +0 -512
- package/extensions/agent-browser/lib/string-enum-schema.ts +0 -20
- package/extensions/agent-browser/lib/temp.ts +0 -577
- package/extensions/agent-browser/lib/web-search.ts +0 -728
- /package/{extensions/agent-browser/lib/orchestration/browser-run.ts → dist/extensions/agent-browser/lib/orchestration/browser-run.js} +0 -0
|
@@ -1,559 +0,0 @@
|
|
|
1
|
-
import { readFile, rm } from "node:fs/promises";
|
|
2
|
-
|
|
3
|
-
import { isCloseCommand, isOpenNavigationCommand } from "../../command-taxonomy.js";
|
|
4
|
-
import { cleanupElectronLaunchResources, inspectElectronLaunchStatus, type ElectronCleanupResult } from "../../electron/cleanup.js";
|
|
5
|
-
import type { ElectronLaunchRecord } from "../../electron/launch.js";
|
|
6
|
-
import { getAllowedDomainsViolation, parseAllowedDomainsPolicyFromArgs } from "../../navigation-policy.js";
|
|
7
|
-
import {
|
|
8
|
-
analyzeNetworkSourceLookupResults,
|
|
9
|
-
analyzeQaPresetResults,
|
|
10
|
-
analyzeQaPresetTimeout,
|
|
11
|
-
analyzeSourceLookupResults,
|
|
12
|
-
buildQaCompactPassText,
|
|
13
|
-
extractQaPageContext,
|
|
14
|
-
redactNetworkSourceLookupAnalysis,
|
|
15
|
-
} from "../../input-modes.js";
|
|
16
|
-
import {
|
|
17
|
-
applyNetworkRouteRecords,
|
|
18
|
-
buildNetworkRouteDiagnostics,
|
|
19
|
-
buildToolPresentation,
|
|
20
|
-
getAgentBrowserErrorText,
|
|
21
|
-
parseAgentBrowserEnvelope,
|
|
22
|
-
type AgentBrowserEnvelope,
|
|
23
|
-
} from "../../results.js";
|
|
24
|
-
import {
|
|
25
|
-
buildEvictedSessionArtifactEntries,
|
|
26
|
-
formatSessionArtifactRetentionSummary,
|
|
27
|
-
mergeSessionArtifactManifest,
|
|
28
|
-
} from "../../results/artifact-manifest.js";
|
|
29
|
-
import type { NetworkRouteRecord, SessionArtifactManifest } from "../../results/contracts.js";
|
|
30
|
-
import { getClipboardWritePayloadCandidates, redactClipboardPermissionEcho, redactClipboardPermissionErrorValue } from "../../results/presentation/errors.js";
|
|
31
|
-
import { shouldCaptureSemanticActionNavigationSummary } from "../../results/presentation/semantic-action.js";
|
|
32
|
-
import {
|
|
33
|
-
commandExplicitlyTargetsAboutBlank,
|
|
34
|
-
deriveSessionTabTarget,
|
|
35
|
-
extractLatestRefSnapshotStateFromBatchResults,
|
|
36
|
-
extractRefSnapshotFromData,
|
|
37
|
-
extractSessionTabTargetFromBatchResults,
|
|
38
|
-
extractSessionTabTargetFromCommandData,
|
|
39
|
-
isAboutBlankSessionTabTarget,
|
|
40
|
-
normalizeSessionTabTarget,
|
|
41
|
-
type SessionRefSnapshot,
|
|
42
|
-
type SessionRefSnapshotInvalidation,
|
|
43
|
-
} from "../../session-page-state.js";
|
|
44
|
-
import type { PersistentSessionArtifactEviction, PersistentSessionArtifactStore } from "../../temp.js";
|
|
45
|
-
import { writePersistentSessionArtifactFile, writeSecureTempFile } from "../../temp.js";
|
|
46
|
-
import { isRecord } from "../../parsing.js";
|
|
47
|
-
import { createFreshSessionName, extractCommandTokens, hasLaunchScopedTabCorrectionFlag, resolveManagedSessionState } from "../../runtime.js";
|
|
48
|
-
import {
|
|
49
|
-
applyOpenResultTabCorrection,
|
|
50
|
-
buildAboutBlankRecoveryHint,
|
|
51
|
-
buildAboutBlankWarning,
|
|
52
|
-
buildElectronPostCommandHealthDiagnostic,
|
|
53
|
-
buildElectronRefFreshnessDiagnostic,
|
|
54
|
-
buildElectronSessionMismatch,
|
|
55
|
-
buildManagedSessionOutcome,
|
|
56
|
-
closeManagedSession,
|
|
57
|
-
collectOpenResultTabCorrection,
|
|
58
|
-
collectSessionTabSelection,
|
|
59
|
-
extractNavigationSummaryFromData,
|
|
60
|
-
extractStringResultField,
|
|
61
|
-
findElectronLaunchRecordForSession,
|
|
62
|
-
formatElectronPostCommandHealthText,
|
|
63
|
-
formatElectronSessionMismatchText,
|
|
64
|
-
getStaleRefArgs,
|
|
65
|
-
mergeNavigationSummaryIntoData,
|
|
66
|
-
shouldCaptureNavigationSummary,
|
|
67
|
-
shouldCorrectSessionTabAfterCommand,
|
|
68
|
-
shouldInspectElectronPostCommandHealth,
|
|
69
|
-
unwrapPinnedSessionBatchEnvelope,
|
|
70
|
-
updateTraceOwnerState,
|
|
71
|
-
} from "./session-state.js";
|
|
72
|
-
import { collectClickDispatchDiagnostic } from "./click-dispatch.js";
|
|
73
|
-
import {
|
|
74
|
-
buildScrollNoopDiagnostic,
|
|
75
|
-
collectComboboxFocusDiagnostic,
|
|
76
|
-
collectElectronBroadGetTextScopeDiagnostics,
|
|
77
|
-
collectElectronHandoff,
|
|
78
|
-
collectFillVerificationDiagnostic,
|
|
79
|
-
collectNavigationSummary,
|
|
80
|
-
collectOverlayBlockerDiagnostic,
|
|
81
|
-
collectQaAttachedTarget,
|
|
82
|
-
collectSnapshotOverlayBlockerDiagnostic,
|
|
83
|
-
collectRecordingDependencyWarning,
|
|
84
|
-
collectScrollPositionSnapshot,
|
|
85
|
-
collectSelectorTextVisibilityDiagnostics,
|
|
86
|
-
collectTimeoutPartialProgress,
|
|
87
|
-
formatQaAttachedTargetText,
|
|
88
|
-
getArtifactCleanupGuidance,
|
|
89
|
-
getEvalResultWarning,
|
|
90
|
-
getEvalStdinHint,
|
|
91
|
-
getSourceLookupElectronContext,
|
|
92
|
-
sleepMs,
|
|
93
|
-
} from "./diagnostics.js";
|
|
94
|
-
import { repairScreenshotData } from "./prepare.js";
|
|
95
|
-
import { getPersistentSessionArtifactStore } from "./session-artifacts.js";
|
|
96
|
-
import {
|
|
97
|
-
buildFinalAgentBrowserToolResult,
|
|
98
|
-
buildRedactedPresentationContent,
|
|
99
|
-
buildWrapperRecoveryHint,
|
|
100
|
-
prepareFinalResultRecoveryState,
|
|
101
|
-
redactExactSensitiveText,
|
|
102
|
-
redactExactSensitiveValue,
|
|
103
|
-
} from "./final-result.js";
|
|
104
|
-
import type {
|
|
105
|
-
AboutBlankSessionMismatch,
|
|
106
|
-
AgentBrowserToolResult,
|
|
107
|
-
BrowserProcessOutputResult,
|
|
108
|
-
BrowserRunContext,
|
|
109
|
-
BrowserRunOptions,
|
|
110
|
-
BrowserRunStatePatch,
|
|
111
|
-
ParseFailureOutput,
|
|
112
|
-
ProcessBrowserOutputInput,
|
|
113
|
-
ScreenshotArtifactRequest,
|
|
114
|
-
ScreenshotPathRequest,
|
|
115
|
-
} from "./types.js";
|
|
116
|
-
|
|
117
|
-
async function repairScreenshotArtifact(options: {
|
|
118
|
-
cwd: string;
|
|
119
|
-
envelope?: AgentBrowserEnvelope;
|
|
120
|
-
request?: ScreenshotPathRequest;
|
|
121
|
-
}): Promise<{ envelope?: AgentBrowserEnvelope; request?: ScreenshotArtifactRequest }> {
|
|
122
|
-
const { cwd, envelope, request } = options;
|
|
123
|
-
if (!request || !envelope || !isRecord(envelope.data)) return { envelope, request };
|
|
124
|
-
const repaired = await repairScreenshotData({ cwd, data: envelope.data, request });
|
|
125
|
-
return { envelope: { ...envelope, data: repaired.data }, request: repaired.request };
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async function repairBatchScreenshotArtifacts(options: {
|
|
129
|
-
cwd: string;
|
|
130
|
-
envelope?: AgentBrowserEnvelope;
|
|
131
|
-
requests?: Array<ScreenshotPathRequest | undefined>;
|
|
132
|
-
}): Promise<{ envelope?: AgentBrowserEnvelope; requests?: Array<ScreenshotArtifactRequest | undefined> }> {
|
|
133
|
-
const { cwd, envelope, requests } = options;
|
|
134
|
-
if (!envelope || !Array.isArray(envelope.data) || !requests?.some((request) => request !== undefined)) return { envelope, requests };
|
|
135
|
-
const repairedRequests: Array<ScreenshotArtifactRequest | undefined> = [];
|
|
136
|
-
const repairedData = await Promise.all(envelope.data.map(async (item, index) => {
|
|
137
|
-
const request = requests[index];
|
|
138
|
-
if (!request || !isRecord(item) || !isRecord(item.result)) return item;
|
|
139
|
-
const repaired = await repairScreenshotData({ cwd, data: item.result, request });
|
|
140
|
-
repairedRequests[index] = repaired.request;
|
|
141
|
-
return { ...item, result: repaired.data };
|
|
142
|
-
}));
|
|
143
|
-
return { envelope: { ...envelope, data: repairedData }, requests: repairedRequests };
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function getEnvelopeErrorString(envelope: AgentBrowserEnvelope | undefined): string | undefined {
|
|
147
|
-
if (!envelope?.error) return undefined;
|
|
148
|
-
if (typeof envelope.error === "string") return envelope.error;
|
|
149
|
-
if (isRecord(envelope.error) && typeof envelope.error.message === "string") return envelope.error.message;
|
|
150
|
-
return String(envelope.error);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
function isStreamEnableAlreadyEnabledNoop(options: { command: string | undefined; envelope: AgentBrowserEnvelope | undefined; processSucceeded: boolean; subcommand: string | undefined }): boolean {
|
|
154
|
-
if (!options.processSucceeded || options.command !== "stream" || options.subcommand !== "enable" || options.envelope?.success !== false) return false;
|
|
155
|
-
const message = (getEnvelopeErrorString(options.envelope) ?? "").trim().replace(/[.!]+$/, "").toLowerCase();
|
|
156
|
-
return message === "streaming is already enabled for this session" || message === "streaming is already enabled" || message === "stream already enabled";
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function batchStartedManagedBrowser(data: unknown): boolean {
|
|
160
|
-
if (!Array.isArray(data)) return false;
|
|
161
|
-
return data.some((entry) => {
|
|
162
|
-
if (!isRecord(entry) || entry.success !== true || !Array.isArray(entry.command)) return false;
|
|
163
|
-
const command = typeof entry.command[0] === "string" ? entry.command[0] : undefined;
|
|
164
|
-
return command === "connect" || command === "goto" || command === "navigate" || isOpenNavigationCommand(command);
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
function setNetworkRouteState(options: { routes?: NetworkRouteRecord[]; routesBySession: Map<string, NetworkRouteRecord[]>; sessionName: string | undefined }): Map<string, NetworkRouteRecord[]> {
|
|
169
|
-
if (!options.sessionName) return options.routesBySession;
|
|
170
|
-
const previousRoutes = options.routesBySession.get(options.sessionName);
|
|
171
|
-
if (options.routes === previousRoutes) return options.routesBySession;
|
|
172
|
-
const next = new Map(options.routesBySession);
|
|
173
|
-
if (options.routes && options.routes.length > 0) next.set(options.sessionName, options.routes);
|
|
174
|
-
else next.delete(options.sessionName);
|
|
175
|
-
return next;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function applyNetworkRouteState(options: { commandTokens: string[]; routesBySession: Map<string, NetworkRouteRecord[]>; sessionName: string | undefined; succeeded: boolean }): Map<string, NetworkRouteRecord[]> {
|
|
179
|
-
const routes = options.sessionName ? applyNetworkRouteRecords(options.routesBySession.get(options.sessionName), options.commandTokens, options.succeeded) : undefined;
|
|
180
|
-
return setNetworkRouteState({ routes, routesBySession: options.routesBySession, sessionName: options.sessionName });
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function applyBatchNetworkRouteState(options: { data: unknown; routesBySession: Map<string, NetworkRouteRecord[]>; sessionName: string | undefined; succeeded: boolean }): Map<string, NetworkRouteRecord[]> {
|
|
184
|
-
if (!options.succeeded || !options.sessionName || !Array.isArray(options.data)) return options.routesBySession;
|
|
185
|
-
let routes = options.routesBySession.get(options.sessionName);
|
|
186
|
-
for (const item of options.data) {
|
|
187
|
-
if (!isRecord(item) || !Array.isArray(item.command) || !item.command.every((token) => typeof token === "string")) continue;
|
|
188
|
-
routes = applyNetworkRouteRecords(routes, extractCommandTokens(item.command as string[]), item.success !== false);
|
|
189
|
-
}
|
|
190
|
-
return setNetworkRouteState({ routes, routesBySession: options.routesBySession, sessionName: options.sessionName });
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export async function preserveParseFailureOutput(options: {
|
|
194
|
-
artifactManifest?: SessionArtifactManifest;
|
|
195
|
-
exactSensitiveValues?: string[];
|
|
196
|
-
persistentArtifactStore?: PersistentSessionArtifactStore;
|
|
197
|
-
stdoutSpillPath?: string;
|
|
198
|
-
}): Promise<ParseFailureOutput> {
|
|
199
|
-
if (!options.stdoutSpillPath) return {};
|
|
200
|
-
try {
|
|
201
|
-
const rawOutput = redactExactSensitiveText(await readFile(options.stdoutSpillPath, "utf8"), options.exactSensitiveValues ?? []);
|
|
202
|
-
const nowMs = Date.now();
|
|
203
|
-
let evictedArtifacts: PersistentSessionArtifactEviction[] = [];
|
|
204
|
-
let fullOutputPath: string;
|
|
205
|
-
let storageScope: "persistent-session" | "process-temp";
|
|
206
|
-
if (options.persistentArtifactStore) {
|
|
207
|
-
const result = await writePersistentSessionArtifactFile({ content: rawOutput, prefix: "pi-agent-browser-parse-failure-output", store: options.persistentArtifactStore, suffix: ".txt" });
|
|
208
|
-
fullOutputPath = result.path;
|
|
209
|
-
evictedArtifacts = result.evictedArtifacts;
|
|
210
|
-
storageScope = "persistent-session";
|
|
211
|
-
} else {
|
|
212
|
-
fullOutputPath = await writeSecureTempFile({ content: rawOutput, prefix: "pi-agent-browser-parse-failure-output", suffix: ".txt" });
|
|
213
|
-
storageScope = "process-temp";
|
|
214
|
-
}
|
|
215
|
-
const artifactManifest = mergeSessionArtifactManifest({
|
|
216
|
-
base: options.artifactManifest,
|
|
217
|
-
entries: [{ command: "agent-browser", createdAtMs: nowMs, kind: "spill", path: fullOutputPath, retentionState: storageScope === "persistent-session" ? "live" : "ephemeral", storageScope }, ...buildEvictedSessionArtifactEntries(evictedArtifacts, nowMs)],
|
|
218
|
-
nowMs,
|
|
219
|
-
});
|
|
220
|
-
return { artifactManifest, artifactRetentionSummary: artifactManifest ? formatSessionArtifactRetentionSummary(artifactManifest) : undefined, fullOutputPath };
|
|
221
|
-
} catch (error) {
|
|
222
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
223
|
-
return { fullOutputUnavailable: message };
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
export async function processBrowserOutput(input: ProcessBrowserOutputInput): Promise<BrowserProcessOutputResult> {
|
|
228
|
-
const { ctx, cwd, electronPostCommandStatusSettleMs, implicitSessionCloseTimeoutMs, sessionPageStateUpdate, signal, state } = input;
|
|
229
|
-
const { prepared, processResult } = input;
|
|
230
|
-
const { electronChildProcesses, electronLaunchRecords, sessionPageState, traceOwners } = state;
|
|
231
|
-
let allowedDomainsBySession = state.allowedDomainsBySession;
|
|
232
|
-
let artifactManifest = state.artifactManifest;
|
|
233
|
-
let freshSessionOrdinal = state.freshSessionOrdinal;
|
|
234
|
-
let managedSessionActive = state.managedSessionActive;
|
|
235
|
-
let managedSessionCwd = state.managedSessionCwd;
|
|
236
|
-
let managedSessionName = state.managedSessionName;
|
|
237
|
-
let networkRoutesBySession = state.networkRoutesBySession;
|
|
238
|
-
try {
|
|
239
|
-
const persistentArtifactStore = getPersistentSessionArtifactStore(ctx);
|
|
240
|
-
const parsed = await parseAgentBrowserEnvelope({ stdout: processResult.stdout, stdoutPath: processResult.stdoutSpillPath });
|
|
241
|
-
let parseError = parsed.parseError;
|
|
242
|
-
let presentationEnvelope = parsed.envelope;
|
|
243
|
-
let navigationSummary = undefined as Awaited<ReturnType<typeof collectNavigationSummary>> | undefined;
|
|
244
|
-
if (prepared.pinnedBatchUnwrapMode) {
|
|
245
|
-
const pinnedBatchResult = unwrapPinnedSessionBatchEnvelope({ envelope: parsed.envelope, includeNavigationSummary: prepared.includePinnedNavigationSummary, mode: prepared.pinnedBatchUnwrapMode });
|
|
246
|
-
parseError = pinnedBatchResult.parseError ?? parseError;
|
|
247
|
-
presentationEnvelope = pinnedBatchResult.envelope ?? presentationEnvelope;
|
|
248
|
-
navigationSummary = pinnedBatchResult.navigationSummary;
|
|
249
|
-
}
|
|
250
|
-
const repairedScreenshot = await repairScreenshotArtifact({ cwd, envelope: presentationEnvelope, request: prepared.preparedArgs.screenshotPathRequest });
|
|
251
|
-
presentationEnvelope = repairedScreenshot.envelope;
|
|
252
|
-
const repairedBatchScreenshots = await repairBatchScreenshotArtifacts({ cwd, envelope: presentationEnvelope, requests: prepared.preparedArgs.batchScreenshotPathRequests });
|
|
253
|
-
presentationEnvelope = repairedBatchScreenshots.envelope;
|
|
254
|
-
const screenshotArtifactRequest = repairedScreenshot.request;
|
|
255
|
-
const batchScreenshotArtifactRequests = repairedBatchScreenshots.requests;
|
|
256
|
-
if (presentationEnvelope && prepared.exactSensitiveValues.length > 0) presentationEnvelope = redactExactSensitiveValue(presentationEnvelope, prepared.exactSensitiveValues) as AgentBrowserEnvelope;
|
|
257
|
-
const parseFailureOutput = parseError ? await preserveParseFailureOutput({ artifactManifest, exactSensitiveValues: prepared.exactSensitiveValues, persistentArtifactStore, stdoutSpillPath: processResult.stdoutSpillPath }) : {};
|
|
258
|
-
const processSucceeded = !processResult.aborted && !processResult.spawnError && processResult.exitCode === 0;
|
|
259
|
-
const plainTextInspection = prepared.executionPlan.plainTextInspection && processSucceeded;
|
|
260
|
-
const parseSucceeded = plainTextInspection || parseError === undefined;
|
|
261
|
-
if (isStreamEnableAlreadyEnabledNoop({ command: prepared.executionPlan.commandInfo.command, envelope: presentationEnvelope, processSucceeded, subcommand: prepared.executionPlan.commandInfo.subcommand })) {
|
|
262
|
-
presentationEnvelope = { success: true, data: { alreadyEnabled: true, enabled: true, message: getEnvelopeErrorString(presentationEnvelope) ?? "Stream already enabled" } };
|
|
263
|
-
}
|
|
264
|
-
const envelopeSuccess = plainTextInspection ? true : presentationEnvelope?.success !== false;
|
|
265
|
-
let succeeded = processSucceeded && parseSucceeded && envelopeSuccess;
|
|
266
|
-
const inspectionText = plainTextInspection ? processResult.stdout.trim() : undefined;
|
|
267
|
-
updateTraceOwnerState({ command: prepared.executionPlan.commandInfo.command, sessionName: prepared.executionPlan.sessionName, subcommand: prepared.executionPlan.commandInfo.subcommand, succeeded, traceOwners });
|
|
268
|
-
|
|
269
|
-
let clickDispatchDiagnostic: Awaited<ReturnType<typeof collectClickDispatchDiagnostic>>;
|
|
270
|
-
if (succeeded && prepared.clickDispatchProbe) {
|
|
271
|
-
clickDispatchDiagnostic = await collectClickDispatchDiagnostic({ cwd, probe: prepared.clickDispatchProbe, sessionName: prepared.executionPlan.sessionName, signal });
|
|
272
|
-
if (clickDispatchDiagnostic) {
|
|
273
|
-
succeeded = false;
|
|
274
|
-
presentationEnvelope = { ...(presentationEnvelope ?? {}), error: clickDispatchDiagnostic.summary, success: false };
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const parsedAllowedDomainsPolicy = parseAllowedDomainsPolicyFromArgs(prepared.runtimeToolArgs);
|
|
279
|
-
const sessionAllowedDomainsPolicy = prepared.executionPlan.sessionName
|
|
280
|
-
? parsedAllowedDomainsPolicy ?? allowedDomainsBySession.get(prepared.executionPlan.sessionName)
|
|
281
|
-
: parsedAllowedDomainsPolicy;
|
|
282
|
-
const shouldCaptureAllowedDomainNavigationSummary = prepared.executionPlan.commandInfo.command === "batch" && sessionAllowedDomainsPolicy !== undefined;
|
|
283
|
-
if (
|
|
284
|
-
succeeded &&
|
|
285
|
-
!navigationSummary &&
|
|
286
|
-
(shouldCaptureNavigationSummary(prepared.executionPlan.commandInfo.command, presentationEnvelope?.data) ||
|
|
287
|
-
shouldCaptureSemanticActionNavigationSummary(prepared.compiledSemanticAction, presentationEnvelope?.data) ||
|
|
288
|
-
shouldCaptureAllowedDomainNavigationSummary)
|
|
289
|
-
) {
|
|
290
|
-
navigationSummary = await collectNavigationSummary({ cwd, sessionName: prepared.executionPlan.sessionName, signal });
|
|
291
|
-
}
|
|
292
|
-
if (navigationSummary && presentationEnvelope && !Array.isArray(presentationEnvelope.data)) presentationEnvelope = { ...presentationEnvelope, data: mergeNavigationSummaryIntoData(presentationEnvelope.data, navigationSummary) };
|
|
293
|
-
let overlayBlockerDiagnostic: Awaited<ReturnType<typeof collectOverlayBlockerDiagnostic>>;
|
|
294
|
-
|
|
295
|
-
let openResultTabCorrection: Awaited<ReturnType<typeof collectOpenResultTabCorrection>>;
|
|
296
|
-
if (succeeded && prepared.executionPlan.sessionName && hasLaunchScopedTabCorrectionFlag(prepared.runtimeToolArgs) && isOpenNavigationCommand(prepared.executionPlan.commandInfo.command)) {
|
|
297
|
-
const targetTitle = extractStringResultField(presentationEnvelope?.data, "title");
|
|
298
|
-
const targetUrl = extractStringResultField(presentationEnvelope?.data, "url");
|
|
299
|
-
const plannedTabCorrection = await collectOpenResultTabCorrection({ cwd, sessionName: prepared.executionPlan.sessionName, signal, targetTitle, targetUrl });
|
|
300
|
-
if (plannedTabCorrection) openResultTabCorrection = await applyOpenResultTabCorrection({ correction: plannedTabCorrection, cwd, sessionName: prepared.executionPlan.sessionName, signal });
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
const observedSessionTabTarget = normalizeSessionTabTarget(navigationSummary) ?? extractSessionTabTargetFromBatchResults(presentationEnvelope?.data) ?? extractSessionTabTargetFromCommandData(prepared.commandTokens, presentationEnvelope?.data);
|
|
304
|
-
let currentSessionTabTarget = deriveSessionTabTarget({ command: prepared.executionPlan.commandInfo.command, data: presentationEnvelope?.data, navigationSummary, previousTarget: prepared.priorSessionTabTarget, subcommand: prepared.executionPlan.commandInfo.subcommand });
|
|
305
|
-
let aboutBlankSessionMismatch: AboutBlankSessionMismatch | undefined;
|
|
306
|
-
let electronPostCommandHealth: ReturnType<typeof buildElectronPostCommandHealthDiagnostic>;
|
|
307
|
-
let electronRefFreshnessDiagnostic: ReturnType<typeof buildElectronRefFreshnessDiagnostic>;
|
|
308
|
-
let electronSessionMismatch: ReturnType<typeof buildElectronSessionMismatch>;
|
|
309
|
-
let electronStatusAfterCommand: Awaited<ReturnType<typeof inspectElectronLaunchStatus>> | undefined;
|
|
310
|
-
const shouldTreatAboutBlankAsMismatch = succeeded && prepared.priorSessionTabTarget !== undefined && !isAboutBlankSessionTabTarget(prepared.priorSessionTabTarget) && isAboutBlankSessionTabTarget(observedSessionTabTarget ?? currentSessionTabTarget) && !commandExplicitlyTargetsAboutBlank(prepared.commandTokens);
|
|
311
|
-
let sessionTabCorrection = prepared.sessionTabCorrection;
|
|
312
|
-
if (shouldTreatAboutBlankAsMismatch && prepared.priorSessionTabTarget) {
|
|
313
|
-
const aboutBlankObservedTarget = observedSessionTabTarget ?? currentSessionTabTarget;
|
|
314
|
-
const aboutBlankRecovery = await collectSessionTabSelection({ cwd, sessionName: prepared.executionPlan.sessionName, signal, target: prepared.priorSessionTabTarget });
|
|
315
|
-
const appliedAboutBlankRecovery = aboutBlankRecovery ? await applyOpenResultTabCorrection({ correction: aboutBlankRecovery, cwd, sessionName: prepared.executionPlan.sessionName, signal }) : undefined;
|
|
316
|
-
if (appliedAboutBlankRecovery) { sessionTabCorrection = appliedAboutBlankRecovery; currentSessionTabTarget = prepared.priorSessionTabTarget; }
|
|
317
|
-
else currentSessionTabTarget = aboutBlankObservedTarget ?? normalizeSessionTabTarget({ url: "about:blank" });
|
|
318
|
-
aboutBlankSessionMismatch = { activeUrl: "about:blank", recoveryApplied: appliedAboutBlankRecovery !== undefined, recoveryHint: buildAboutBlankRecoveryHint(), targetTitle: prepared.priorSessionTabTarget.title, targetUrl: prepared.priorSessionTabTarget.url };
|
|
319
|
-
const electronRecord = findElectronLaunchRecordForSession(prepared.executionPlan.sessionName, electronLaunchRecords);
|
|
320
|
-
if (electronRecord && prepared.executionPlan.sessionName) {
|
|
321
|
-
electronStatusAfterCommand = await inspectElectronLaunchStatus(electronRecord);
|
|
322
|
-
electronSessionMismatch = buildElectronSessionMismatch({ managedSession: { sessionName: prepared.executionPlan.sessionName, title: aboutBlankObservedTarget?.title, url: aboutBlankObservedTarget?.url ?? "about:blank" }, record: electronRecord, statusTargets: electronStatusAfterCommand.targets });
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
if (succeeded && prepared.priorSessionTabTarget && !sessionTabCorrection && !aboutBlankSessionMismatch && !commandExplicitlyTargetsAboutBlank(prepared.commandTokens) && observedSessionTabTarget && shouldCorrectSessionTabAfterCommand({ command: prepared.executionPlan.commandInfo.command, pinningRequired: prepared.sessionTabPinningReason !== undefined, sessionName: prepared.executionPlan.sessionName })) {
|
|
326
|
-
const postCommandTabCorrection = await collectSessionTabSelection({ cwd, sessionName: prepared.executionPlan.sessionName, signal, target: observedSessionTabTarget });
|
|
327
|
-
if (postCommandTabCorrection) {
|
|
328
|
-
const appliedPostCommandCorrection = await applyOpenResultTabCorrection({ correction: postCommandTabCorrection, cwd, sessionName: prepared.executionPlan.sessionName, signal });
|
|
329
|
-
if (appliedPostCommandCorrection && !sessionTabCorrection) sessionTabCorrection = appliedPostCommandCorrection;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
if (succeeded && prepared.executionPlan.sessionName && parsedAllowedDomainsPolicy) {
|
|
333
|
-
allowedDomainsBySession = new Map(allowedDomainsBySession);
|
|
334
|
-
allowedDomainsBySession.set(prepared.executionPlan.sessionName, parsedAllowedDomainsPolicy);
|
|
335
|
-
}
|
|
336
|
-
const allowedDomainsViolation = succeeded ? getAllowedDomainsViolation({
|
|
337
|
-
policy: sessionAllowedDomainsPolicy,
|
|
338
|
-
url: currentSessionTabTarget?.url ?? observedSessionTabTarget?.url ?? navigationSummary?.url,
|
|
339
|
-
}) : undefined;
|
|
340
|
-
if (allowedDomainsViolation) {
|
|
341
|
-
succeeded = false;
|
|
342
|
-
presentationEnvelope = { ...(presentationEnvelope ?? {}), error: allowedDomainsViolation.summary, success: false };
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
const electronRecordForCommand = findElectronLaunchRecordForSession(prepared.executionPlan.sessionName, electronLaunchRecords);
|
|
346
|
-
if (succeeded && electronRecordForCommand && shouldInspectElectronPostCommandHealth(prepared.executionPlan.commandInfo.command)) {
|
|
347
|
-
electronStatusAfterCommand ??= await inspectElectronLaunchStatus(electronRecordForCommand);
|
|
348
|
-
electronPostCommandHealth = buildElectronPostCommandHealthDiagnostic({ command: prepared.executionPlan.commandInfo.command, record: electronRecordForCommand, status: electronStatusAfterCommand, target: observedSessionTabTarget ?? currentSessionTabTarget });
|
|
349
|
-
if (electronPostCommandHealth && electronPostCommandHealth.reason !== "process-dead") {
|
|
350
|
-
await sleepMs(electronPostCommandStatusSettleMs);
|
|
351
|
-
electronStatusAfterCommand = await inspectElectronLaunchStatus(electronRecordForCommand);
|
|
352
|
-
electronPostCommandHealth = buildElectronPostCommandHealthDiagnostic({ command: prepared.executionPlan.commandInfo.command, record: electronRecordForCommand, status: electronStatusAfterCommand, target: observedSessionTabTarget ?? currentSessionTabTarget });
|
|
353
|
-
}
|
|
354
|
-
if (electronPostCommandHealth) succeeded = false;
|
|
355
|
-
}
|
|
356
|
-
let fillVerificationDiagnostic: Awaited<ReturnType<typeof collectFillVerificationDiagnostic>>;
|
|
357
|
-
let selectorTextVisibilityDiagnostics: Awaited<ReturnType<typeof collectSelectorTextVisibilityDiagnostics>> = [];
|
|
358
|
-
let electronBroadGetTextScopeDiagnostics: ReturnType<typeof collectElectronBroadGetTextScopeDiagnostics> = [];
|
|
359
|
-
const timeoutPartialProgress = processResult.timedOut ? await collectTimeoutPartialProgress({ command: prepared.executionPlan.commandInfo.command, compiledJob: prepared.compiledJob, cwd, sessionName: prepared.executionPlan.sessionName, stdin: prepared.runtimeToolStdin }) : undefined;
|
|
360
|
-
if (succeeded) {
|
|
361
|
-
const fillRefSnapshot = prepared.resolvedSemanticActionRefSnapshot ?? prepared.priorRefSnapshotState;
|
|
362
|
-
fillVerificationDiagnostic = await collectFillVerificationDiagnostic({ commandTokens: prepared.commandTokens, cwd, forceValueVerification: electronRecordForCommand !== undefined, refSnapshot: fillRefSnapshot, sessionName: prepared.executionPlan.sessionName, signal });
|
|
363
|
-
}
|
|
364
|
-
if (succeeded && electronRecordForCommand) {
|
|
365
|
-
electronRefFreshnessDiagnostic = buildElectronRefFreshnessDiagnostic({ command: prepared.executionPlan.commandInfo.command, commandTokens: prepared.commandTokens, record: electronRecordForCommand, sessionName: prepared.executionPlan.sessionName, stdin: prepared.runtimeToolStdin });
|
|
366
|
-
}
|
|
367
|
-
if (succeeded && prepared.executionPlan.commandInfo.command === "snapshot") {
|
|
368
|
-
overlayBlockerDiagnostic = collectSnapshotOverlayBlockerDiagnostic(presentationEnvelope?.data);
|
|
369
|
-
}
|
|
370
|
-
if (succeeded && !overlayBlockerDiagnostic && !sessionTabCorrection && !aboutBlankSessionMismatch && !electronRecordForCommand && !clickDispatchDiagnostic) overlayBlockerDiagnostic = await collectOverlayBlockerDiagnostic({ command: prepared.executionPlan.commandInfo.command, cwd, data: presentationEnvelope?.data, navigationSummary, priorTarget: prepared.priorSessionTabTarget, sessionName: prepared.executionPlan.sessionName, signal });
|
|
371
|
-
if (succeeded) {
|
|
372
|
-
selectorTextVisibilityDiagnostics = await collectSelectorTextVisibilityDiagnostics({ commandInfo: prepared.executionPlan.commandInfo, commandTokens: prepared.commandTokens, cwd, data: presentationEnvelope?.data, sessionName: prepared.executionPlan.sessionName, signal });
|
|
373
|
-
if (electronRecordForCommand) electronBroadGetTextScopeDiagnostics = collectElectronBroadGetTextScopeDiagnostics({ commandInfo: prepared.executionPlan.commandInfo, commandTokens: prepared.commandTokens, currentTarget: currentSessionTabTarget, data: presentationEnvelope?.data, electronLaunchRecords, priorTarget: prepared.priorSessionTabTarget, sessionName: prepared.executionPlan.sessionName });
|
|
374
|
-
}
|
|
375
|
-
const activeNetworkRoutes = prepared.executionPlan.sessionName ? networkRoutesBySession.get(prepared.executionPlan.sessionName) : undefined;
|
|
376
|
-
const networkRouteDiagnostics = succeeded && prepared.executionPlan.commandInfo.command === "network" && prepared.executionPlan.commandInfo.subcommand === "requests" && prepared.executionPlan.sessionName
|
|
377
|
-
? buildNetworkRouteDiagnostics(presentationEnvelope?.data, activeNetworkRoutes)
|
|
378
|
-
: undefined;
|
|
379
|
-
networkRoutesBySession = applyNetworkRouteState({ commandTokens: prepared.commandTokens, routesBySession: networkRoutesBySession, sessionName: prepared.executionPlan.sessionName, succeeded });
|
|
380
|
-
const comboboxFocusDiagnostic = succeeded ? await collectComboboxFocusDiagnostic({ command: prepared.executionPlan.commandInfo.command, commandTokens: prepared.commandTokens, cwd, semanticAction: prepared.compiledSemanticAction, sessionName: prepared.executionPlan.sessionName, signal }) : undefined;
|
|
381
|
-
const recordingDependencyWarning = await collectRecordingDependencyWarning({ command: prepared.executionPlan.commandInfo.command, commandTokens: prepared.commandTokens, succeeded });
|
|
382
|
-
const scrollNoopDiagnostic = succeeded && prepared.shouldProbeScrollNoop ? buildScrollNoopDiagnostic(prepared.scrollPositionBefore, await collectScrollPositionSnapshot({ cwd, sessionName: prepared.executionPlan.sessionName, signal })) : undefined;
|
|
383
|
-
let currentRefSnapshot: SessionRefSnapshot | undefined;
|
|
384
|
-
let currentRefSnapshotInvalidation: SessionRefSnapshotInvalidation | undefined;
|
|
385
|
-
const batchRefSnapshotState = prepared.executionPlan.commandInfo.command === "batch" ? extractLatestRefSnapshotStateFromBatchResults(presentationEnvelope?.data) : undefined;
|
|
386
|
-
if (prepared.executionPlan.sessionName) {
|
|
387
|
-
if (isCloseCommand(prepared.executionPlan.commandInfo.command) && succeeded) {
|
|
388
|
-
allowedDomainsBySession = new Map(allowedDomainsBySession);
|
|
389
|
-
allowedDomainsBySession.delete(prepared.executionPlan.sessionName);
|
|
390
|
-
networkRoutesBySession = new Map(networkRoutesBySession);
|
|
391
|
-
networkRoutesBySession.delete(prepared.executionPlan.sessionName);
|
|
392
|
-
sessionPageState.clearSession(prepared.executionPlan.sessionName);
|
|
393
|
-
state.closedManagedSessionNames.add(prepared.executionPlan.sessionName);
|
|
394
|
-
} else if (currentSessionTabTarget) {
|
|
395
|
-
const tabUpdate = sessionPageState.applyTabTarget({ sessionName: prepared.executionPlan.sessionName, target: currentSessionTabTarget, update: sessionPageStateUpdate });
|
|
396
|
-
if (!tabUpdate.applied && succeeded) sessionPageState.markPinning(prepared.executionPlan.sessionName, "drift");
|
|
397
|
-
}
|
|
398
|
-
const refSnapshot = prepared.executionPlan.commandInfo.command === "batch" ? batchRefSnapshotState?.snapshot : succeeded ? prepared.executionPlan.commandInfo.command === "snapshot" ? extractRefSnapshotFromData(presentationEnvelope?.data) : prepared.resolvedSemanticActionRefSnapshot ?? overlayBlockerDiagnostic?.snapshot : undefined;
|
|
399
|
-
if (refSnapshot) {
|
|
400
|
-
const refUpdate = sessionPageState.applyRefSnapshot({ fallbackTarget: currentSessionTabTarget, sessionName: prepared.executionPlan.sessionName, snapshot: refSnapshot, update: sessionPageStateUpdate });
|
|
401
|
-
currentRefSnapshot = refUpdate.refSnapshot;
|
|
402
|
-
currentRefSnapshotInvalidation = refUpdate.refSnapshotInvalidation;
|
|
403
|
-
} else {
|
|
404
|
-
const stateView = sessionPageState.get(prepared.executionPlan.sessionName);
|
|
405
|
-
currentRefSnapshot = stateView.refSnapshot;
|
|
406
|
-
currentRefSnapshotInvalidation = stateView.refSnapshotInvalidation;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
const priorManagedSessionActive = managedSessionActive;
|
|
411
|
-
const priorManagedSessionCwd = managedSessionCwd;
|
|
412
|
-
const priorManagedSessionName = managedSessionName;
|
|
413
|
-
const commandClosesSession = isCloseCommand(prepared.executionPlan.commandInfo.command);
|
|
414
|
-
const managedCloseSessionName = commandClosesSession && succeeded && prepared.executionPlan.sessionName === priorManagedSessionName
|
|
415
|
-
? prepared.executionPlan.sessionName
|
|
416
|
-
: prepared.executionPlan.managedSessionName;
|
|
417
|
-
const policyBlockedFreshManagedSession = allowedDomainsViolation !== undefined && prepared.sessionMode === "fresh" && prepared.executionPlan.managedSessionName === prepared.executionPlan.sessionName;
|
|
418
|
-
const postLaunchBatchFailure = !succeeded && processSucceeded && parseSucceeded && prepared.sessionMode === "fresh" && prepared.executionPlan.commandInfo.command === "batch" && batchStartedManagedBrowser(presentationEnvelope?.data);
|
|
419
|
-
const postLaunchTimeoutWithPage = !succeeded && processResult.timedOut && prepared.sessionMode === "fresh" && prepared.executionPlan.commandInfo.command === "batch" && timeoutPartialProgress?.liveUrlRecovered === true;
|
|
420
|
-
const managedTransitionSucceeded = succeeded || policyBlockedFreshManagedSession || postLaunchBatchFailure || postLaunchTimeoutWithPage;
|
|
421
|
-
const managedSessionState = resolveManagedSessionState({ command: prepared.executionPlan.commandInfo.command, managedSessionName: managedCloseSessionName, priorActive: priorManagedSessionActive, priorSessionName: priorManagedSessionName, succeeded: managedTransitionSucceeded });
|
|
422
|
-
const replacedManagedSessionName = managedSessionState.replacedSessionName;
|
|
423
|
-
managedSessionActive = managedSessionState.active;
|
|
424
|
-
managedSessionName = managedSessionState.sessionName;
|
|
425
|
-
if (commandClosesSession && succeeded && managedCloseSessionName === priorManagedSessionName && !managedSessionActive) {
|
|
426
|
-
freshSessionOrdinal += 1;
|
|
427
|
-
managedSessionName = createFreshSessionName(state.managedSessionBaseName, state.ephemeralSessionSeed, freshSessionOrdinal);
|
|
428
|
-
}
|
|
429
|
-
let managedSessionOutcome = buildManagedSessionOutcome({ activeAfter: managedSessionActive, activeBefore: priorManagedSessionActive, attemptedSessionName: managedCloseSessionName, command: prepared.executionPlan.commandInfo.command, currentSessionName: managedSessionName, previousSessionName: priorManagedSessionName, replacedSessionName: replacedManagedSessionName, sessionMode: prepared.sessionMode, succeeded: managedTransitionSucceeded });
|
|
430
|
-
if (prepared.executionPlan.managedSessionName && succeeded) managedSessionCwd = cwd;
|
|
431
|
-
if (prepared.executionPlan.sessionName && succeeded) {
|
|
432
|
-
if (openResultTabCorrection || sessionTabCorrection || aboutBlankSessionMismatch?.recoveryApplied) sessionPageState.markPinning(prepared.executionPlan.sessionName, "drift");
|
|
433
|
-
else if (prepared.sessionTabPinningReason === "restore") sessionPageState.clearRestorePinning(prepared.executionPlan.sessionName);
|
|
434
|
-
}
|
|
435
|
-
if (replacedManagedSessionName) {
|
|
436
|
-
allowedDomainsBySession = new Map(allowedDomainsBySession);
|
|
437
|
-
allowedDomainsBySession.delete(replacedManagedSessionName);
|
|
438
|
-
networkRoutesBySession = new Map(networkRoutesBySession);
|
|
439
|
-
networkRoutesBySession.delete(replacedManagedSessionName);
|
|
440
|
-
sessionPageState.clearSession(replacedManagedSessionName);
|
|
441
|
-
const replacedCloseError = await closeManagedSession({ cwd: priorManagedSessionCwd, sessionName: replacedManagedSessionName, timeoutMs: implicitSessionCloseTimeoutMs });
|
|
442
|
-
if (!replacedCloseError) state.closedManagedSessionNames.add(replacedManagedSessionName);
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
let electronLaunchRecord: ElectronLaunchRecord | undefined;
|
|
446
|
-
let electronFailedConnectCleanup: ElectronCleanupResult | undefined = prepared.electronFailedConnectCleanup;
|
|
447
|
-
let electronHandoff = prepared.electronHandoff;
|
|
448
|
-
if (prepared.electronLaunch) {
|
|
449
|
-
if (succeeded && prepared.executionPlan.sessionName) {
|
|
450
|
-
electronLaunchRecord = { ...prepared.electronLaunch.record, sessionName: prepared.executionPlan.sessionName };
|
|
451
|
-
electronLaunchRecords.set(electronLaunchRecord.launchId, electronLaunchRecord);
|
|
452
|
-
electronChildProcesses.set(electronLaunchRecord.launchId, prepared.electronLaunch.child);
|
|
453
|
-
const electronHandoffMode = prepared.compiledElectron?.action === "launch" ? prepared.compiledElectron.handoff : "connect";
|
|
454
|
-
try { electronHandoff = await collectElectronHandoff({ cwd, handoff: electronHandoffMode, sessionName: prepared.executionPlan.sessionName, signal }); }
|
|
455
|
-
catch (error) { electronHandoff = { error: error instanceof Error ? error.message : String(error), handoff: electronHandoffMode }; }
|
|
456
|
-
if (electronHandoff?.refSnapshot) {
|
|
457
|
-
const refUpdate = sessionPageState.applyRefSnapshot({ sessionName: prepared.executionPlan.sessionName, snapshot: electronHandoff.refSnapshot, update: sessionPageStateUpdate });
|
|
458
|
-
currentRefSnapshot = refUpdate.refSnapshot;
|
|
459
|
-
currentRefSnapshotInvalidation = refUpdate.refSnapshotInvalidation;
|
|
460
|
-
if (electronHandoff.refSnapshot.target) {
|
|
461
|
-
currentSessionTabTarget = electronHandoff.refSnapshot.target;
|
|
462
|
-
sessionPageState.applyTabTarget({ sessionName: prepared.executionPlan.sessionName, target: electronHandoff.refSnapshot.target, update: sessionPageStateUpdate });
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
} else {
|
|
466
|
-
electronFailedConnectCleanup = await cleanupElectronLaunchResources({ child: prepared.electronLaunch.child, record: prepared.electronLaunch.record, timeoutMs: implicitSessionCloseTimeoutMs });
|
|
467
|
-
electronLaunchRecord = electronFailedConnectCleanup.record;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
let errorText = getAgentBrowserErrorText({ aborted: processResult.aborted, command: prepared.executionPlan.commandInfo.command, effectiveArgs: prepared.redactedProcessArgs, envelope: presentationEnvelope, exitCode: processResult.exitCode, parseError, plainTextInspection, staleRefArgs: getStaleRefArgs(prepared.commandTokens, prepared.runtimeToolStdin), spawnError: processResult.spawnError, stderr: processResult.stderr, timedOut: processResult.timedOut, timeoutMs: processResult.timeoutMs, wrapperRecoveryHint: buildWrapperRecoveryHint({ pinnedBatchUnwrapMode: prepared.pinnedBatchUnwrapMode, sessionTabCorrection }) });
|
|
472
|
-
if (errorText) {
|
|
473
|
-
const clipboardWritePayloadCandidates = getClipboardWritePayloadCandidates(prepared.commandTokens);
|
|
474
|
-
errorText = redactClipboardPermissionEcho(prepared.executionPlan.commandInfo, errorText);
|
|
475
|
-
if (presentationEnvelope?.error !== undefined) presentationEnvelope = { ...presentationEnvelope, error: redactClipboardPermissionErrorValue(prepared.executionPlan.commandInfo, presentationEnvelope.error, clipboardWritePayloadCandidates) };
|
|
476
|
-
}
|
|
477
|
-
const presentation = plainTextInspection ? { artifacts: undefined, batchFailure: undefined, batchSteps: undefined, content: [{ type: "text" as const, text: inspectionText ?? "" }], data: undefined, fullOutputPath: undefined, fullOutputPaths: undefined, imagePath: undefined, imagePaths: undefined, savedFile: undefined, savedFilePath: undefined, summary: `${prepared.redactedArgs.join(" ")} completed` } : await buildToolPresentation({ args: prepared.redactedProcessArgs, artifactManifest, artifactRequest: screenshotArtifactRequest, batchArtifactRequests: batchScreenshotArtifactRequests, commandInfo: prepared.executionPlan.commandInfo, compiledSemanticAction: prepared.compiledSemanticAction, cwd, envelope: presentationEnvelope, errorText, networkRouteDiagnostics, networkRoutes: activeNetworkRoutes, persistentArtifactStore, sessionName: prepared.executionPlan.sessionName });
|
|
478
|
-
networkRoutesBySession = applyBatchNetworkRouteState({ data: presentationEnvelope?.data, routesBySession: networkRoutesBySession, sessionName: prepared.executionPlan.sessionName, succeeded });
|
|
479
|
-
if (presentation.resultCategory === "failure" && succeeded) {
|
|
480
|
-
succeeded = false;
|
|
481
|
-
presentationEnvelope = { ...(presentationEnvelope ?? {}), error: presentation.summary, success: false };
|
|
482
|
-
}
|
|
483
|
-
if (scrollNoopDiagnostic) {
|
|
484
|
-
presentation.summary = "Scroll completed with no observed movement.";
|
|
485
|
-
if (isRecord(presentation.data)) presentation.data = { ...presentation.data, noMovement: true, scrolled: false };
|
|
486
|
-
if (presentation.content[0]?.type === "text") presentation.content[0] = { ...presentation.content[0], text: `Scroll completed with no observed movement.\n\n${presentation.content[0].text}` };
|
|
487
|
-
else presentation.content.unshift({ type: "text", text: "Scroll completed with no observed movement." });
|
|
488
|
-
}
|
|
489
|
-
if (parseFailureOutput.artifactManifest) { presentation.artifactManifest = parseFailureOutput.artifactManifest; presentation.artifactRetentionSummary = parseFailureOutput.artifactRetentionSummary; }
|
|
490
|
-
if (parseFailureOutput.fullOutputPath || parseFailureOutput.fullOutputUnavailable) {
|
|
491
|
-
const existingText = presentation.content[0]?.type === "text" ? presentation.content[0].text : "";
|
|
492
|
-
const noticeLines = [parseFailureOutput.fullOutputPath ? `Full output path: ${parseFailureOutput.fullOutputPath}` : `Full raw output unavailable: ${parseFailureOutput.fullOutputUnavailable}`, parseFailureOutput.artifactRetentionSummary].filter((item): item is string => item !== undefined);
|
|
493
|
-
const notice = noticeLines.join("\n");
|
|
494
|
-
presentation.content[0] = { type: "text", text: existingText.length > 0 ? `${existingText}\n\n${notice}` : notice };
|
|
495
|
-
}
|
|
496
|
-
if (presentation.artifactManifest) artifactManifest = presentation.artifactManifest;
|
|
497
|
-
const qaPreset = prepared.compiledQaPreset
|
|
498
|
-
? (processResult.timedOut ? analyzeQaPresetTimeout(prepared.compiledQaPreset) ?? analyzeQaPresetResults(presentationEnvelope?.data, prepared.compiledQaPreset) : analyzeQaPresetResults(presentationEnvelope?.data, prepared.compiledQaPreset))
|
|
499
|
-
: undefined;
|
|
500
|
-
let qaAttachedTarget = prepared.compiledQaPreset?.checks.attached
|
|
501
|
-
? await collectQaAttachedTarget({ currentTarget: currentSessionTabTarget ?? prepared.priorSessionTabTarget, cwd, sessionName: prepared.executionPlan.sessionName, signal })
|
|
502
|
-
: undefined;
|
|
503
|
-
const sourceLookupElectronContext = prepared.compiledSourceLookup ? getSourceLookupElectronContext({ currentTarget: currentSessionTabTarget, electronLaunchRecords, priorTarget: prepared.priorSessionTabTarget, sessionName: prepared.executionPlan.sessionName }) : undefined;
|
|
504
|
-
const sourceLookup = prepared.compiledSourceLookup ? await analyzeSourceLookupResults(presentationEnvelope?.data, prepared.compiledSourceLookup, cwd, { electronContext: sourceLookupElectronContext, workspaceRoot: cwd }) : undefined;
|
|
505
|
-
const networkSourceLookup = prepared.compiledNetworkSourceLookup ? redactNetworkSourceLookupAnalysis(await analyzeNetworkSourceLookupResults(presentationEnvelope?.data, prepared.compiledNetworkSourceLookup, cwd)) : undefined;
|
|
506
|
-
if (networkSourceLookup && presentation.content[0]?.type === "text") presentation.content[0] = { ...presentation.content[0], text: `${networkSourceLookup.summary}\n\n${presentation.content[0].text}` };
|
|
507
|
-
else if (networkSourceLookup) presentation.content.unshift({ type: "text", text: networkSourceLookup.summary });
|
|
508
|
-
if (sourceLookup && presentation.content[0]?.type === "text") presentation.content[0] = { ...presentation.content[0], text: `${sourceLookup.summary}\n\n${presentation.content[0].text}` };
|
|
509
|
-
else if (sourceLookup) presentation.content.unshift({ type: "text", text: sourceLookup.summary });
|
|
510
|
-
if (qaPreset && !qaPreset.passed && presentation.failureCategory !== "artifact-missing") {
|
|
511
|
-
succeeded = false;
|
|
512
|
-
presentation.failureCategory = "qa-failure";
|
|
513
|
-
presentation.summary = qaPreset.summary;
|
|
514
|
-
if (presentation.content[0]?.type === "text") presentation.content[0] = { ...presentation.content[0], text: `${qaPreset.summary}\n\n${presentation.content[0].text}` };
|
|
515
|
-
else presentation.content.unshift({ type: "text", text: qaPreset.summary });
|
|
516
|
-
} else if (qaPreset?.passed && prepared.compiledQaPreset && succeeded) {
|
|
517
|
-
const compactText = buildQaCompactPassText({
|
|
518
|
-
artifactVerification: presentation.artifactVerification,
|
|
519
|
-
batchStepCount: presentation.batchSteps?.length ?? prepared.compiledQaPreset.steps.length,
|
|
520
|
-
checks: prepared.compiledQaPreset.checks,
|
|
521
|
-
page: extractQaPageContext({
|
|
522
|
-
attachedTarget: qaAttachedTarget,
|
|
523
|
-
batchData: presentationEnvelope?.data,
|
|
524
|
-
compiled: prepared.compiledQaPreset,
|
|
525
|
-
}),
|
|
526
|
-
qaPreset,
|
|
527
|
-
});
|
|
528
|
-
presentation.summary = qaPreset.summary;
|
|
529
|
-
const nonTextContent = presentation.content.filter((item) => item.type !== "text");
|
|
530
|
-
presentation.content = [{ type: "text", text: compactText }, ...nonTextContent];
|
|
531
|
-
}
|
|
532
|
-
const qaAttachedTargetText = formatQaAttachedTargetText(qaAttachedTarget);
|
|
533
|
-
const qaAttachedDiagnosticsText = prepared.compiledQaPreset?.checks.attached && prepared.compiledQaPreset.checks.diagnosticsResetAtStart === false && (prepared.compiledQaPreset.checks.checkNetwork || prepared.compiledQaPreset.checks.checkConsole || prepared.compiledQaPreset.checks.checkErrors)
|
|
534
|
-
? "Attached diagnostics: existing upstream session console/network/error buffers were preserved; rows may include events from before qa.attached started."
|
|
535
|
-
: undefined;
|
|
536
|
-
const qaAttachedBannerText = [qaAttachedTargetText, qaAttachedDiagnosticsText].filter((part): part is string => typeof part === "string" && part.length > 0).join("\n");
|
|
537
|
-
const skipAttachedTargetBanner = qaPreset?.passed && prepared.compiledQaPreset?.checks.attached;
|
|
538
|
-
if (!skipAttachedTargetBanner && qaAttachedBannerText && presentation.content[0]?.type === "text") presentation.content[0] = { ...presentation.content[0], text: `${qaAttachedBannerText}\n\n${presentation.content[0].text}` };
|
|
539
|
-
else if (!skipAttachedTargetBanner && qaAttachedBannerText) presentation.content.unshift({ type: "text", text: qaAttachedBannerText });
|
|
540
|
-
if (managedSessionOutcome && managedSessionOutcome.succeeded !== succeeded) managedSessionOutcome = { ...managedSessionOutcome, succeeded };
|
|
541
|
-
const evalNavigationSummary = navigationSummary ?? extractNavigationSummaryFromData(presentationEnvelope?.data);
|
|
542
|
-
const evalSessionTabUrl = prepared.executionPlan.sessionName ? sessionPageState.get(prepared.executionPlan.sessionName).tabTarget?.url : undefined;
|
|
543
|
-
const evalPageUrl = evalNavigationSummary?.url ?? currentSessionTabTarget?.url ?? prepared.priorSessionTabTarget?.url ?? evalSessionTabUrl;
|
|
544
|
-
const evalStdinHint = getEvalStdinHint({ command: prepared.executionPlan.commandInfo.command, data: presentationEnvelope?.data, stdin: prepared.runtimeToolStdin });
|
|
545
|
-
const evalResultWarning = getEvalResultWarning({ command: prepared.executionPlan.commandInfo.command, data: presentationEnvelope?.data, navigationSummary: evalNavigationSummary, pageUrl: evalPageUrl, stdin: prepared.runtimeToolStdin });
|
|
546
|
-
const resultArtifactManifest = presentation.artifactManifest ?? artifactManifest;
|
|
547
|
-
const artifactCleanup = await getArtifactCleanupGuidance({ command: prepared.executionPlan.commandInfo.command, cwd, manifest: resultArtifactManifest, succeeded });
|
|
548
|
-
const warningText = electronPostCommandHealth ? formatElectronPostCommandHealthText(electronPostCommandHealth) : electronSessionMismatch ? formatElectronSessionMismatchText(electronSessionMismatch) : aboutBlankSessionMismatch ? buildAboutBlankWarning(aboutBlankSessionMismatch) : undefined;
|
|
549
|
-
const redactedContent = buildRedactedPresentationContent({ exactSensitiveValues: prepared.exactSensitiveValues, plainTextInspection, presentation, presentationEnvelope, succeeded, userRequestedJson: prepared.userRequestedJson, warningText });
|
|
550
|
-
const finalRecoveryState = await prepareFinalResultRecoveryState({ aboutBlankSessionMismatch, batchRefSnapshotState, commandTokens: prepared.commandTokens, compiledSemanticAction: prepared.compiledSemanticAction, currentRefSnapshot, currentRefSnapshotInvalidation, currentSessionTabTarget, cwd, electronPostCommandHealth, errorText, executionPlan: prepared.executionPlan, parseError, plainTextInspection, presentation, processResult, redactedProcessArgs: prepared.redactedProcessArgs, runtimeToolArgs: prepared.runtimeToolArgs, sessionPageState, sessionPageStateUpdate, sessionTabCorrection, signal, succeeded });
|
|
551
|
-
currentRefSnapshot = finalRecoveryState.currentRefSnapshot;
|
|
552
|
-
currentRefSnapshotInvalidation = finalRecoveryState.currentRefSnapshotInvalidation;
|
|
553
|
-
const result = buildFinalAgentBrowserToolResult({ aboutBlankSessionMismatch, artifactCleanup, categoryDetails: finalRecoveryState.categoryDetails, clickDispatchDiagnostic, commandTokens: prepared.commandTokens, comboboxFocusDiagnostic, compiledNetworkSourceLookup: prepared.compiledNetworkSourceLookup, compiledSemanticAction: prepared.compiledSemanticAction, compatibilityWorkaround: prepared.compatibilityWorkaround, currentRefSnapshot, currentRefSnapshotInvalidation, currentSessionTabTarget, electronBroadGetTextScopeDiagnostics, electronFailedConnectCleanup, electronHandoff, electronLaunch: prepared.electronLaunch, electronLaunchRecord, electronLaunchRecords, electronPostCommandHealth, electronProfileIsolationDetails: input.electronProfileIsolationDetails, electronRefFreshnessDiagnostic, electronSessionMismatch, errorText, evalResultWarning, evalStdinHint, exactSensitiveValues: prepared.exactSensitiveValues, executionPlan: prepared.executionPlan, fillVerificationDiagnostic, inspectionText, managedSessionOutcome, navigationSummary, networkSourceLookup, noActivePageSnapshotFailure: finalRecoveryState.noActivePageSnapshotFailure, openResultTabCorrection, overlayBlockerDiagnostic, parseError, parseFailureOutput, parseSucceeded, plainTextInspection, presentation, presentationEnvelope, priorSessionTabTarget: prepared.priorSessionTabTarget, processResult, qaAttachedTarget, qaPreset, recordingDependencyWarning, redactedArgs: prepared.redactedArgs, redactedCompiledElectron: prepared.redactedCompiledElectron, redactedCompiledJob: prepared.redactedCompiledJob, redactedCompiledNetworkSourceLookup: prepared.redactedCompiledNetworkSourceLookup, redactedCompiledQaPreset: prepared.redactedCompiledQaPreset, redactedCompiledSemanticAction: prepared.redactedCompiledSemanticAction, redactedCompiledSourceLookup: prepared.redactedCompiledSourceLookup, redactedContent, redactedProcessArgs: prepared.redactedProcessArgs, redactedRecoveryHint: prepared.redactedRecoveryHint, resultArtifactManifest, richInputRecoveryDiagnostic: finalRecoveryState.richInputRecoveryDiagnostic, scrollNoopDiagnostic, selectorTextVisibilityDiagnostics, sessionMode: prepared.sessionMode, sessionTabCorrection, sourceLookup, succeeded, timeoutPartialProgress, userRequestedJson: prepared.userRequestedJson, visibleRefFallbackDiagnostic: finalRecoveryState.visibleRefFallbackDiagnostic, visibleRefFallbackSessionName: finalRecoveryState.visibleRefFallbackSessionName });
|
|
554
|
-
const statePatch: BrowserRunStatePatch = { allowedDomainsBySession, artifactManifest, freshSessionOrdinal, managedSessionActive, managedSessionCwd, managedSessionName, networkRoutesBySession };
|
|
555
|
-
return { result, statePatch };
|
|
556
|
-
} finally {
|
|
557
|
-
if (processResult.stdoutSpillPath) await rm(processResult.stdoutSpillPath, { force: true }).catch(() => undefined);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { isAbsolute, resolve } from "node:path";
|
|
2
|
-
|
|
3
|
-
import { isCloseCommand } from "../../command-taxonomy.js";
|
|
4
|
-
import { executableExistsOnPath } from "../../executable-path.js";
|
|
5
|
-
import type { SessionArtifactManifest } from "../../results/contracts.js";
|
|
6
|
-
import type { PromptPolicy, PromptRequestedArtifact } from "../../prompt-policy.js";
|
|
7
|
-
|
|
8
|
-
export interface RequestedArtifactCloseViolation {
|
|
9
|
-
message: string;
|
|
10
|
-
missingArtifacts: PromptRequestedArtifact[];
|
|
11
|
-
reason: "requested-artifacts-missing-before-close";
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function resolveArtifactPath(cwd: string, path: string): string {
|
|
15
|
-
return isAbsolute(path) ? path : resolve(cwd, path);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function manifestContainsArtifact(manifest: SessionArtifactManifest | undefined, cwd: string, artifact: PromptRequestedArtifact): boolean {
|
|
19
|
-
if (!manifest) return false;
|
|
20
|
-
const requestedAbsolutePath = resolveArtifactPath(cwd, artifact.path);
|
|
21
|
-
const expectedKind = artifact.kind === "screenshot" ? "image" : "video";
|
|
22
|
-
return manifest.entries.some((entry) => {
|
|
23
|
-
const entryAbsolutePath = entry.absolutePath ?? resolveArtifactPath(cwd, entry.path);
|
|
24
|
-
return entry.storageScope === "explicit-path" && entry.kind === expectedKind && entryAbsolutePath === requestedAbsolutePath && entry.retentionState === "live" && entry.exists === true;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function isArtifactRequired(artifact: PromptRequestedArtifact): Promise<boolean> {
|
|
29
|
-
if (artifact.required) return true;
|
|
30
|
-
return artifact.kind === "recording" && await executableExistsOnPath("ffmpeg");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function findRequestedArtifactCloseViolation(options: { artifactManifest?: SessionArtifactManifest; command: string | undefined; cwd: string; promptPolicy: PromptPolicy }): Promise<RequestedArtifactCloseViolation | undefined> {
|
|
34
|
-
if (!isCloseCommand(options.command)) return undefined;
|
|
35
|
-
const missingArtifacts: PromptRequestedArtifact[] = [];
|
|
36
|
-
for (const artifact of options.promptPolicy.requestedArtifacts) {
|
|
37
|
-
if (!await isArtifactRequired(artifact)) continue;
|
|
38
|
-
if (!manifestContainsArtifact(options.artifactManifest, options.cwd, artifact)) missingArtifacts.push(artifact);
|
|
39
|
-
}
|
|
40
|
-
if (missingArtifacts.length === 0) return undefined;
|
|
41
|
-
const missingList = missingArtifacts.map((artifact) => `${artifact.kind}: ${artifact.path}`).join(", ");
|
|
42
|
-
return {
|
|
43
|
-
message: `Blocked browser close because requested artifact path${missingArtifacts.length === 1 ? " is" : "s are"} missing or unverified: ${missingList}. Save the requested artifact path first, or report why an optional artifact is unavailable before closing.`,
|
|
44
|
-
missingArtifacts,
|
|
45
|
-
reason: "requested-artifacts-missing-before-close",
|
|
46
|
-
};
|
|
47
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { PersistentSessionArtifactStore } from "../../temp.js";
|
|
2
|
-
import type { BrowserRunContext } from "./types.js";
|
|
3
|
-
|
|
4
|
-
export function getPersistentSessionArtifactStore(ctx: BrowserRunContext): PersistentSessionArtifactStore | undefined {
|
|
5
|
-
const sessionDir = typeof ctx.sessionManager.getSessionDir === "function" ? ctx.sessionManager.getSessionDir() : undefined;
|
|
6
|
-
const sessionId = ctx.sessionManager.getSessionId();
|
|
7
|
-
return sessionDir && sessionId ? { sessionDir, sessionId } : undefined;
|
|
8
|
-
}
|