@nuanu-ai/agentbrowse 0.2.47 → 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/README.md +81 -10
- package/dist/agentpay-gateway.d.ts +9 -0
- package/dist/agentpay-gateway.d.ts.map +1 -1
- package/dist/agentpay-gateway.js +31 -1
- package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
- package/dist/agentpay-stagehand-llm.js +9 -1
- package/dist/command-api-tracing.d.ts +19 -0
- package/dist/command-api-tracing.d.ts.map +1 -0
- package/dist/command-api-tracing.js +137 -0
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +822 -670
- package/dist/commands/act.test-harness.d.ts +6 -0
- package/dist/commands/act.test-harness.d.ts.map +1 -1
- package/dist/commands/act.test-harness.js +44 -1
- package/dist/commands/action-acceptance.d.ts.map +1 -1
- package/dist/commands/action-acceptance.js +115 -0
- package/dist/commands/captcha-solve.d.ts.map +1 -1
- package/dist/commands/captcha-solve.js +83 -16
- package/dist/commands/click-action-executor.d.ts +0 -1
- package/dist/commands/click-action-executor.d.ts.map +1 -1
- package/dist/commands/click-action-executor.js +31 -77
- package/dist/commands/close.d.ts +3 -3
- package/dist/commands/close.d.ts.map +1 -1
- package/dist/commands/close.js +178 -0
- package/dist/commands/descriptor-validation.d.ts.map +1 -1
- package/dist/commands/descriptor-validation.js +75 -57
- package/dist/commands/end-session.d.ts +25 -0
- package/dist/commands/end-session.d.ts.map +1 -0
- package/dist/commands/end-session.js +161 -0
- package/dist/commands/extract-stagehand-executor.js +1 -1
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +339 -202
- package/dist/commands/fill-secret.d.ts +3 -3
- package/dist/commands/fill-secret.d.ts.map +1 -1
- package/dist/commands/fill-secret.js +419 -234
- package/dist/commands/get-secrets-catalog.d.ts.map +1 -1
- package/dist/commands/get-secrets-catalog.js +66 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +6 -3
- package/dist/commands/interaction-kernel.d.ts +46 -0
- package/dist/commands/interaction-kernel.d.ts.map +1 -0
- package/dist/commands/interaction-kernel.js +215 -0
- package/dist/commands/launch.d.ts +1 -3
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +115 -27
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +188 -45
- package/dist/commands/observe-accessibility.d.ts.map +1 -1
- package/dist/commands/observe-accessibility.js +46 -39
- package/dist/commands/observe-dom-label-contract.d.ts.map +1 -1
- package/dist/commands/observe-dom-label-contract.js +5 -0
- package/dist/commands/observe-inventory.d.ts +13 -0
- package/dist/commands/observe-inventory.d.ts.map +1 -1
- package/dist/commands/observe-inventory.js +320 -65
- package/dist/commands/observe-persistence.d.ts.map +1 -1
- package/dist/commands/observe-persistence.js +3 -0
- package/dist/commands/observe-projection.d.ts +1 -0
- package/dist/commands/observe-projection.d.ts.map +1 -1
- package/dist/commands/observe-projection.js +7 -2
- package/dist/commands/observe-protected.d.ts +1 -0
- package/dist/commands/observe-protected.d.ts.map +1 -1
- package/dist/commands/observe-protected.js +9 -4
- package/dist/commands/observe-semantics.d.ts.map +1 -1
- package/dist/commands/observe-semantics.js +5 -2
- package/dist/commands/observe-stagehand.d.ts +1 -0
- package/dist/commands/observe-stagehand.d.ts.map +1 -1
- package/dist/commands/observe-stagehand.js +2 -0
- package/dist/commands/observe.d.ts +2 -0
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +387 -203
- package/dist/commands/observe.test-harness.d.ts +8 -0
- package/dist/commands/observe.test-harness.d.ts.map +1 -1
- package/dist/commands/observe.test-harness.js +48 -1
- package/dist/commands/poll-secret.d.ts +6 -0
- package/dist/commands/poll-secret.d.ts.map +1 -0
- package/dist/commands/poll-secret.js +159 -0
- package/dist/commands/request-secret.d.ts +6 -0
- package/dist/commands/request-secret.d.ts.map +1 -0
- package/dist/commands/request-secret.js +284 -0
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +172 -7
- package/dist/commands/select-action-executor.d.ts.map +1 -1
- package/dist/commands/semantic-observe.d.ts +4 -0
- package/dist/commands/semantic-observe.d.ts.map +1 -1
- package/dist/commands/semantic-observe.js +388 -17
- package/dist/commands/start-session.d.ts +31 -0
- package/dist/commands/start-session.d.ts.map +1 -0
- package/dist/commands/start-session.js +347 -0
- package/dist/commands/status.d.ts +2 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +166 -144
- package/dist/control-semantics.d.ts +1 -0
- package/dist/control-semantics.d.ts.map +1 -1
- package/dist/control-semantics.js +51 -9
- package/dist/generated/build-config.d.ts +2 -0
- package/dist/generated/build-config.d.ts.map +1 -0
- package/dist/generated/build-config.js +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +163 -63
- package/dist/otel-exporter.d.ts +58 -0
- package/dist/otel-exporter.d.ts.map +1 -0
- package/dist/otel-exporter.js +263 -0
- package/dist/otel-projector.d.ts +75 -0
- package/dist/otel-projector.d.ts.map +1 -0
- package/dist/otel-projector.js +409 -0
- package/dist/owned-browser.d.ts +1 -1
- package/dist/owned-browser.d.ts.map +1 -1
- package/dist/owned-browser.js +13 -1
- package/dist/owned-process.d.ts +2 -0
- package/dist/owned-process.d.ts.map +1 -1
- package/dist/owned-process.js +7 -3
- package/dist/playwright-runtime.d.ts +1 -1
- package/dist/playwright-runtime.d.ts.map +1 -1
- package/dist/playwright-runtime.js +8 -8
- package/dist/run-observability.d.ts +25 -0
- package/dist/run-observability.d.ts.map +1 -0
- package/dist/run-observability.js +115 -0
- package/dist/run-store.d.ts +274 -0
- package/dist/run-store.d.ts.map +1 -0
- package/dist/run-store.js +631 -0
- package/dist/runtime-metrics.d.ts +27 -0
- package/dist/runtime-metrics.d.ts.map +1 -0
- package/dist/runtime-metrics.js +66 -0
- package/dist/runtime-page-state.d.ts +11 -0
- package/dist/runtime-page-state.d.ts.map +1 -0
- package/dist/runtime-page-state.js +62 -0
- package/dist/runtime-protected-state.d.ts +16 -0
- package/dist/runtime-protected-state.d.ts.map +1 -0
- package/dist/runtime-protected-state.js +157 -0
- package/dist/runtime-state.d.ts +10 -44
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +57 -222
- package/dist/secrets/backend.d.ts +65 -16
- package/dist/secrets/backend.d.ts.map +1 -1
- package/dist/secrets/backend.js +135 -95
- package/dist/secrets/catalog-sync.d.ts.map +1 -1
- package/dist/secrets/catalog-sync.js +4 -1
- package/dist/secrets/form-matcher.d.ts +5 -5
- package/dist/secrets/form-matcher.d.ts.map +1 -1
- package/dist/secrets/form-matcher.js +292 -164
- package/dist/secrets/intent-output.d.ts +6 -10
- package/dist/secrets/intent-output.d.ts.map +1 -1
- package/dist/secrets/intent-output.js +4 -58
- package/dist/secrets/mock-agentpay-cabinet.d.ts +38 -27
- package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -1
- package/dist/secrets/mock-agentpay-cabinet.js +177 -111
- package/dist/secrets/protected-artifact-guard.d.ts +2 -2
- package/dist/secrets/protected-artifact-guard.d.ts.map +1 -1
- package/dist/secrets/protected-artifact-guard.js +2 -2
- package/dist/secrets/protected-bindings.d.ts +1 -1
- package/dist/secrets/protected-bindings.d.ts.map +1 -1
- package/dist/secrets/protected-bindings.js +6 -0
- package/dist/secrets/protected-field-semantics.d.ts +9 -0
- package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
- package/dist/secrets/protected-field-semantics.js +154 -0
- package/dist/secrets/protected-field-values.d.ts.map +1 -1
- package/dist/secrets/protected-field-values.js +3 -3
- package/dist/secrets/protected-fill.d.ts +1 -1
- package/dist/secrets/protected-fill.d.ts.map +1 -1
- package/dist/secrets/protected-fill.js +45 -149
- package/dist/secrets/protected-value-adapters.d.ts +2 -1
- package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
- package/dist/secrets/protected-value-adapters.js +80 -1
- package/dist/secrets/request-output.d.ts +11 -0
- package/dist/secrets/request-output.d.ts.map +1 -0
- package/dist/secrets/request-output.js +75 -0
- package/dist/secrets/types.d.ts +15 -9
- package/dist/secrets/types.d.ts.map +1 -1
- package/dist/secrets/types.js +3 -0
- package/dist/session-event-exporter.d.ts +36 -0
- package/dist/session-event-exporter.d.ts.map +1 -0
- package/dist/session-event-exporter.js +428 -0
- package/dist/session.d.ts +16 -7
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +150 -23
- package/dist/sessions-backend.d.ts +354 -0
- package/dist/sessions-backend.d.ts.map +1 -0
- package/dist/sessions-backend.js +126 -0
- package/dist/solver/browser-launcher.d.ts +1 -1
- package/dist/solver/browser-launcher.d.ts.map +1 -1
- package/dist/solver/browser-launcher.js +39 -13
- package/dist/solver/captcha-solver.d.ts.map +1 -1
- package/dist/solver/captcha-solver.js +8 -1
- package/dist/solver/config.d.ts +0 -1
- package/dist/solver/config.d.ts.map +1 -1
- package/dist/solver/config.js +0 -22
- package/dist/solver/types.d.ts +1 -0
- package/dist/solver/types.d.ts.map +1 -1
- package/dist/workflow-session-completion.d.ts +33 -0
- package/dist/workflow-session-completion.d.ts.map +1 -0
- package/dist/workflow-session-completion.js +156 -0
- package/package.json +11 -1
- package/dist/commands/create-intent.d.ts +0 -6
- package/dist/commands/create-intent.d.ts.map +0 -1
- package/dist/commands/create-intent.js +0 -75
- package/dist/commands/poll-intent.d.ts +0 -6
- package/dist/commands/poll-intent.d.ts.map +0 -1
- package/dist/commands/poll-intent.js +0 -57
package/dist/commands/close.js
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
* browse close — Close the browser and clean up session.
|
|
3
3
|
*/
|
|
4
4
|
import { deleteSession, isOwnedSession, loadSession } from '../session.js';
|
|
5
|
+
import { finishRunRecord, finishRunStep, pruneLocalRuns, startRunStep } from '../run-store.js';
|
|
6
|
+
import { appendCommandLifecycleEventBestEffort, captureStepSnapshotBestEffort, } from '../run-observability.js';
|
|
7
|
+
import { exportRunRootToOtlpHttpJsonBestEffort, exportRunStepToOtlpHttpJsonBestEffort, } from '../otel-exporter.js';
|
|
5
8
|
import { info } from '../output.js';
|
|
6
9
|
import { closeOwnedBrowser } from '../owned-browser.js';
|
|
7
10
|
import { isManagedBrowserPid } from '../owned-process.js';
|
|
11
|
+
import { completeWorkflowSessionRemote } from '../workflow-session-completion.js';
|
|
8
12
|
function isCloseableManagedSession(session) {
|
|
9
13
|
if (!session) {
|
|
10
14
|
return false;
|
|
@@ -14,11 +18,100 @@ function isCloseableManagedSession(session) {
|
|
|
14
18
|
}
|
|
15
19
|
return !session.identity && isManagedBrowserPid(session.pid);
|
|
16
20
|
}
|
|
21
|
+
function formatUnknownError(error) {
|
|
22
|
+
if (error instanceof Error) {
|
|
23
|
+
return error.message;
|
|
24
|
+
}
|
|
25
|
+
if (typeof error === 'string') {
|
|
26
|
+
return error;
|
|
27
|
+
}
|
|
28
|
+
if (error && typeof error === 'object') {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.stringify(error);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return Object.prototype.toString.call(error);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return String(error);
|
|
37
|
+
}
|
|
38
|
+
async function finalizeRunBestEffort(runId, options) {
|
|
39
|
+
if (!runId) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
finishRunRecord(runId, {
|
|
44
|
+
status: options.status,
|
|
45
|
+
finalOutcome: {
|
|
46
|
+
success: options.success,
|
|
47
|
+
outcomeType: options.outcomeType,
|
|
48
|
+
message: options.message,
|
|
49
|
+
...(options.reason ? { reason: options.reason } : {}),
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
info(`[close] failed to finalize local run ${runId}: ${formatUnknownError(error)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function pruneLocalRunsBestEffort() {
|
|
58
|
+
try {
|
|
59
|
+
const result = pruneLocalRuns();
|
|
60
|
+
if (result.deletedRunIds.length > 0) {
|
|
61
|
+
info(`[close] pruned stale local run${result.deletedRunIds.length === 1 ? '' : 's'} ${result.deletedRunIds.join(', ')}`);
|
|
62
|
+
}
|
|
63
|
+
if (result.failedRunIds.length > 0) {
|
|
64
|
+
info(`[close] failed to prune local run${result.failedRunIds.length === 1 ? '' : 's'} ${result.failedRunIds.map((entry) => `${entry.runId}: ${entry.reason}`).join('; ')}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
info(`[close] local run prune failed: ${formatUnknownError(error)}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
17
71
|
export async function close() {
|
|
18
72
|
const session = loadSession();
|
|
73
|
+
const closeStep = session?.activeRunId
|
|
74
|
+
? startRunStep({
|
|
75
|
+
runId: session.activeRunId,
|
|
76
|
+
command: 'close',
|
|
77
|
+
input: {
|
|
78
|
+
hadSession: session !== null,
|
|
79
|
+
closeableManagedSession: isCloseableManagedSession(session),
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
: null;
|
|
83
|
+
if (session) {
|
|
84
|
+
captureStepSnapshotBestEffort({
|
|
85
|
+
session,
|
|
86
|
+
step: closeStep,
|
|
87
|
+
phase: 'before',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
appendCommandLifecycleEventBestEffort({
|
|
91
|
+
step: closeStep,
|
|
92
|
+
phase: 'started',
|
|
93
|
+
attributes: {
|
|
94
|
+
hadSession: session !== null,
|
|
95
|
+
closeableManagedSession: isCloseableManagedSession(session),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
19
98
|
if (isCloseableManagedSession(session)) {
|
|
20
99
|
const closeResult = await closeOwnedBrowser(session);
|
|
21
100
|
if (!closeResult.success) {
|
|
101
|
+
appendCommandLifecycleEventBestEffort({
|
|
102
|
+
step: closeStep,
|
|
103
|
+
phase: 'failed',
|
|
104
|
+
attributes: {
|
|
105
|
+
outcomeType: 'browser_close_failed',
|
|
106
|
+
reason: closeResult.reason,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
await finalizeStepBestEffort(session?.activeRunId, closeStep?.stepId, {
|
|
110
|
+
success: false,
|
|
111
|
+
outcomeType: 'browser_close_failed',
|
|
112
|
+
message: 'Browser close failed.',
|
|
113
|
+
reason: closeResult.reason,
|
|
114
|
+
});
|
|
22
115
|
info(`Owned browser close failed; keeping session record: ${closeResult.reason}`);
|
|
23
116
|
return {
|
|
24
117
|
success: false,
|
|
@@ -30,8 +123,93 @@ export async function close() {
|
|
|
30
123
|
}
|
|
31
124
|
info(`Closed owned browser via ${closeResult.method}`);
|
|
32
125
|
}
|
|
126
|
+
if (session?.intentSessionId) {
|
|
127
|
+
const remoteCompletion = await completeWorkflowSessionRemote({
|
|
128
|
+
session,
|
|
129
|
+
stepId: closeStep?.stepId,
|
|
130
|
+
command: 'close',
|
|
131
|
+
terminalStatus: 'canceled',
|
|
132
|
+
runStatus: 'aborted',
|
|
133
|
+
summary: 'Browser session closed before the workflow completed.',
|
|
134
|
+
outcomeType: 'workflow_session_canceled',
|
|
135
|
+
message: 'Workflow session canceled because the browser was closed.',
|
|
136
|
+
reason: 'The active browser session was closed by the close command.',
|
|
137
|
+
});
|
|
138
|
+
if (!remoteCompletion.success) {
|
|
139
|
+
const reason = remoteCompletion.reason;
|
|
140
|
+
const failureError = remoteCompletion.error === 'backend_session_complete_failed'
|
|
141
|
+
? 'workflow_session_complete_failed'
|
|
142
|
+
: remoteCompletion.error;
|
|
143
|
+
const failureMessage = 'Browser closed but workflow session completion failed.';
|
|
144
|
+
appendCommandLifecycleEventBestEffort({
|
|
145
|
+
step: closeStep,
|
|
146
|
+
phase: 'failed',
|
|
147
|
+
attributes: {
|
|
148
|
+
outcomeType: remoteCompletion.error === 'backend_session_complete_failed'
|
|
149
|
+
? 'workflow_session_complete_failed'
|
|
150
|
+
: remoteCompletion.error,
|
|
151
|
+
reason,
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
await finalizeStepBestEffort(session?.activeRunId, closeStep?.stepId, {
|
|
155
|
+
success: false,
|
|
156
|
+
outcomeType: remoteCompletion.error === 'backend_session_complete_failed'
|
|
157
|
+
? 'workflow_session_complete_failed'
|
|
158
|
+
: remoteCompletion.error,
|
|
159
|
+
message: failureMessage,
|
|
160
|
+
reason,
|
|
161
|
+
skipExport: true,
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
success: false,
|
|
165
|
+
error: failureError,
|
|
166
|
+
outcomeType: remoteCompletion.error === 'backend_session_complete_failed' ? 'failed' : 'blocked',
|
|
167
|
+
message: failureMessage,
|
|
168
|
+
reason,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
appendCommandLifecycleEventBestEffort({
|
|
173
|
+
step: closeStep,
|
|
174
|
+
phase: 'completed',
|
|
175
|
+
attributes: {
|
|
176
|
+
outcomeType: 'browser_closed',
|
|
177
|
+
},
|
|
178
|
+
});
|
|
33
179
|
if (session) {
|
|
34
180
|
deleteSession();
|
|
35
181
|
}
|
|
182
|
+
await finalizeStepBestEffort(session?.activeRunId, closeStep?.stepId, {
|
|
183
|
+
success: true,
|
|
184
|
+
outcomeType: 'browser_closed',
|
|
185
|
+
message: 'Browser session closed.',
|
|
186
|
+
});
|
|
187
|
+
await finalizeRunBestEffort(session?.activeRunId, {
|
|
188
|
+
status: 'aborted',
|
|
189
|
+
success: false,
|
|
190
|
+
outcomeType: 'browser_closed',
|
|
191
|
+
message: 'Browser session closed.',
|
|
192
|
+
reason: 'The active browser session was closed by the close command.',
|
|
193
|
+
});
|
|
194
|
+
await exportRunRootToOtlpHttpJsonBestEffort(session?.activeRunId);
|
|
195
|
+
pruneLocalRunsBestEffort();
|
|
36
196
|
return { success: true };
|
|
37
197
|
}
|
|
198
|
+
async function finalizeStepBestEffort(runId, stepId, options) {
|
|
199
|
+
if (!runId || !stepId) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
try {
|
|
203
|
+
finishRunStep({
|
|
204
|
+
runId,
|
|
205
|
+
stepId,
|
|
206
|
+
...options,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
info(`[close] failed to finalize local run step ${stepId}: ${formatUnknownError(error)}`);
|
|
211
|
+
}
|
|
212
|
+
if (!options.skipExport) {
|
|
213
|
+
await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"descriptor-validation.d.ts","sourceRoot":"","sources":["../../src/commands/descriptor-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED,eAAO,MAAM,4BAA4B,QAaxC,CAAC;AAEF,iBAAS,gCAAgC,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEzE;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;
|
|
1
|
+
{"version":3,"file":"descriptor-validation.d.ts","sourceRoot":"","sources":["../../src/commands/descriptor-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED,eAAO,MAAM,4BAA4B,QAaxC,CAAC;AAEF,iBAAS,gCAAgC,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEzE;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAiGF,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWtF;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAWxC;AAOD,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,gBAAgB,EACxB,QAAQ,EAAE,sBAAsB,GAAG,IAAI,GACtC,OAAO,CAoCT;AAED,eAAO,MAAM,0BAA0B;;;;;CAKtC,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQnF"}
|
|
@@ -46,6 +46,78 @@ const LOCATOR_BINDING_SNAPSHOT_SCRIPT = String.raw `
|
|
|
46
46
|
autocomplete: element.getAttribute('autocomplete')?.trim() || undefined,
|
|
47
47
|
};
|
|
48
48
|
`;
|
|
49
|
+
const LOCATOR_OUTER_HTML_SCRIPT = String.raw `
|
|
50
|
+
if (!(element instanceof HTMLElement)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const ownerWindow = element.ownerDocument?.defaultView || window;
|
|
55
|
+
const TextCtor = ownerWindow.Text;
|
|
56
|
+
const ElementCtor = ownerWindow.Element;
|
|
57
|
+
const ShadowRootCtor = ownerWindow.ShadowRoot;
|
|
58
|
+
const voidTags = new Set([
|
|
59
|
+
'area',
|
|
60
|
+
'base',
|
|
61
|
+
'br',
|
|
62
|
+
'col',
|
|
63
|
+
'embed',
|
|
64
|
+
'hr',
|
|
65
|
+
'img',
|
|
66
|
+
'input',
|
|
67
|
+
'link',
|
|
68
|
+
'meta',
|
|
69
|
+
'param',
|
|
70
|
+
'source',
|
|
71
|
+
'track',
|
|
72
|
+
'wbr',
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
const escapeText = (value) =>
|
|
76
|
+
value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
77
|
+
|
|
78
|
+
const escapeAttribute = (value) =>
|
|
79
|
+
value.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
80
|
+
|
|
81
|
+
const serializeChildren = (parent) =>
|
|
82
|
+
Array.from(parent.childNodes)
|
|
83
|
+
.map((node) => serializeNode(node))
|
|
84
|
+
.join('');
|
|
85
|
+
|
|
86
|
+
const serializeNode = (node) => {
|
|
87
|
+
if (node instanceof TextCtor) {
|
|
88
|
+
return escapeText(node.textContent ?? '');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!(node instanceof ElementCtor)) {
|
|
92
|
+
return '';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const tag = node.tagName.toLowerCase();
|
|
96
|
+
if (['script', 'style', 'noscript', 'template'].includes(tag)) {
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const attrs = node
|
|
101
|
+
.getAttributeNames()
|
|
102
|
+
.sort()
|
|
103
|
+
.map((name) => ' ' + name + '="' + escapeAttribute(node.getAttribute(name) ?? '') + '"')
|
|
104
|
+
.join('');
|
|
105
|
+
const shadowRoot =
|
|
106
|
+
node.shadowRoot && node.shadowRoot instanceof ShadowRootCtor ? node.shadowRoot : null;
|
|
107
|
+
const shadowHtml = shadowRoot
|
|
108
|
+
? '<div data-agentbrowse-shadow-root="open">' + serializeChildren(shadowRoot) + '</div>'
|
|
109
|
+
: '';
|
|
110
|
+
const childHtml = serializeChildren(node);
|
|
111
|
+
|
|
112
|
+
if (voidTags.has(tag)) {
|
|
113
|
+
return '<' + tag + attrs + '>' + shadowHtml;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return '<' + tag + attrs + '>' + shadowHtml + childHtml + '</' + tag + '>';
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
return serializeNode(element);
|
|
120
|
+
`;
|
|
49
121
|
export async function readLocatorDomSignature(locator) {
|
|
50
122
|
try {
|
|
51
123
|
return await locator
|
|
@@ -110,63 +182,9 @@ export const __testDescriptorValidation = {
|
|
|
110
182
|
};
|
|
111
183
|
export async function readLocatorOuterHtml(locator) {
|
|
112
184
|
try {
|
|
113
|
-
return await locator
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
const ownerWindow = element.ownerDocument?.defaultView || window;
|
|
118
|
-
const TextCtor = ownerWindow.Text;
|
|
119
|
-
const ElementCtor = ownerWindow.Element;
|
|
120
|
-
const ShadowRootCtor = ownerWindow.ShadowRoot;
|
|
121
|
-
const voidTags = new Set([
|
|
122
|
-
'area',
|
|
123
|
-
'base',
|
|
124
|
-
'br',
|
|
125
|
-
'col',
|
|
126
|
-
'embed',
|
|
127
|
-
'hr',
|
|
128
|
-
'img',
|
|
129
|
-
'input',
|
|
130
|
-
'link',
|
|
131
|
-
'meta',
|
|
132
|
-
'param',
|
|
133
|
-
'source',
|
|
134
|
-
'track',
|
|
135
|
-
'wbr',
|
|
136
|
-
]);
|
|
137
|
-
const escapeText = (value) => value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
138
|
-
const escapeAttribute = (value) => value.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
139
|
-
const serializeChildren = (parent) => Array.from(parent.childNodes)
|
|
140
|
-
.map((node) => serializeNode(node))
|
|
141
|
-
.join('');
|
|
142
|
-
const serializeNode = (node) => {
|
|
143
|
-
if (node instanceof TextCtor) {
|
|
144
|
-
return escapeText(node.textContent ?? '');
|
|
145
|
-
}
|
|
146
|
-
if (!(node instanceof ElementCtor)) {
|
|
147
|
-
return '';
|
|
148
|
-
}
|
|
149
|
-
const tag = node.tagName.toLowerCase();
|
|
150
|
-
if (['script', 'style', 'noscript', 'template'].includes(tag)) {
|
|
151
|
-
return '';
|
|
152
|
-
}
|
|
153
|
-
const attrs = node
|
|
154
|
-
.getAttributeNames()
|
|
155
|
-
.sort()
|
|
156
|
-
.map((name) => ` ${name}="${escapeAttribute(node.getAttribute(name) ?? '')}"`)
|
|
157
|
-
.join('');
|
|
158
|
-
const shadowRoot = node.shadowRoot && node.shadowRoot instanceof ShadowRootCtor ? node.shadowRoot : null;
|
|
159
|
-
const shadowHtml = shadowRoot
|
|
160
|
-
? `<div data-agentbrowse-shadow-root="open">${serializeChildren(shadowRoot)}</div>`
|
|
161
|
-
: '';
|
|
162
|
-
const childHtml = serializeChildren(node);
|
|
163
|
-
if (voidTags.has(tag)) {
|
|
164
|
-
return `<${tag}${attrs}>${shadowHtml}`;
|
|
165
|
-
}
|
|
166
|
-
return `<${tag}${attrs}>${shadowHtml}${childHtml}</${tag}>`;
|
|
167
|
-
};
|
|
168
|
-
return serializeNode(element);
|
|
169
|
-
});
|
|
185
|
+
return await locator
|
|
186
|
+
.first()
|
|
187
|
+
.evaluate((element, source) => Function('element', source)(element), LOCATOR_OUTER_HTML_SCRIPT);
|
|
170
188
|
}
|
|
171
189
|
catch {
|
|
172
190
|
return null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* browse end-session — Mark the current workflow session as completed without closing the browser.
|
|
3
|
+
*/
|
|
4
|
+
import { type BrowseSession } from '../session.js';
|
|
5
|
+
export type EndSessionSuccessResult = {
|
|
6
|
+
success: true;
|
|
7
|
+
runId: string;
|
|
8
|
+
intentSessionId: string;
|
|
9
|
+
status: string;
|
|
10
|
+
lastEventSeq: number;
|
|
11
|
+
browserSessionId: string | null;
|
|
12
|
+
completedAt: string;
|
|
13
|
+
outcomeType: 'workflow_session_completed';
|
|
14
|
+
message: 'Workflow session completed.';
|
|
15
|
+
};
|
|
16
|
+
export type EndSessionFailureResult = {
|
|
17
|
+
success: false;
|
|
18
|
+
error: 'workflow_session_unavailable' | 'workflow_run_unavailable' | 'workflow_step_unavailable' | 'backend_session_complete_failed';
|
|
19
|
+
outcomeType: 'blocked' | 'failed';
|
|
20
|
+
message: 'Workflow session end failed.';
|
|
21
|
+
reason: string;
|
|
22
|
+
};
|
|
23
|
+
export type EndSessionResult = EndSessionSuccessResult | EndSessionFailureResult;
|
|
24
|
+
export declare function endSession(session: BrowseSession): Promise<EndSessionResult>;
|
|
25
|
+
//# sourceMappingURL=end-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"end-session.d.ts","sourceRoot":"","sources":["../../src/commands/end-session.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAOhE,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,4BAA4B,CAAC;IAC1C,OAAO,EAAE,6BAA6B,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EACD,8BAA8B,GAC9B,0BAA0B,GAC1B,2BAA2B,GAC3B,iCAAiC,CAAC;IACtC,WAAW,EAAE,SAAS,GAAG,QAAQ,CAAC;IAClC,OAAO,EAAE,8BAA8B,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,uBAAuB,GAAG,uBAAuB,CAAC;AA0DjF,wBAAsB,UAAU,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA0IlF"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* browse end-session — Mark the current workflow session as completed without closing the browser.
|
|
3
|
+
*/
|
|
4
|
+
import { withApiTraceContext } from '../command-api-tracing.js';
|
|
5
|
+
import { exportRunRootToOtlpHttpJsonBestEffort, exportRunStepToOtlpHttpJsonBestEffort, } from '../otel-exporter.js';
|
|
6
|
+
import { info } from '../output.js';
|
|
7
|
+
import { appendCommandLifecycleEventBestEffort, captureStepSnapshotBestEffort, } from '../run-observability.js';
|
|
8
|
+
import { finishRunRecord, finishRunStep, startRunStep } from '../run-store.js';
|
|
9
|
+
import { saveSession } from '../session.js';
|
|
10
|
+
import { clearWorkflowState, completeWorkflowSessionRemote, formatUnknownWorkflowCompletionError, } from '../workflow-session-completion.js';
|
|
11
|
+
function finalizeEndSessionStepBestEffort(runId, stepId, options) {
|
|
12
|
+
if (!runId || !stepId) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
finishRunStep({
|
|
17
|
+
runId,
|
|
18
|
+
stepId,
|
|
19
|
+
...options,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
info(`[end-session] failed to finalize local run step ${stepId}: ${formatUnknownWorkflowCompletionError(error)}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function finalizeRunRecordBestEffort(runId, options) {
|
|
27
|
+
if (!runId) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
finishRunRecord(runId, {
|
|
32
|
+
status: options.status,
|
|
33
|
+
finalOutcome: {
|
|
34
|
+
success: options.success,
|
|
35
|
+
...(options.outcomeType ? { outcomeType: options.outcomeType } : {}),
|
|
36
|
+
...(options.message ? { message: options.message } : {}),
|
|
37
|
+
...(options.reason ? { reason: options.reason } : {}),
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
info(`[end-session] failed to finalize local run ${runId}: ${formatUnknownWorkflowCompletionError(error)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function endSession(session) {
|
|
46
|
+
const endSessionStep = session.activeRunId
|
|
47
|
+
? startRunStep({
|
|
48
|
+
runId: session.activeRunId,
|
|
49
|
+
command: 'end-session',
|
|
50
|
+
input: {
|
|
51
|
+
hasWorkflowSession: Boolean(session.intentSessionId),
|
|
52
|
+
currentRequestId: session.currentRequestId ?? null,
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
: null;
|
|
56
|
+
const endSessionStepHandle = session.activeRunId && endSessionStep?.stepId
|
|
57
|
+
? {
|
|
58
|
+
runId: session.activeRunId,
|
|
59
|
+
stepId: endSessionStep.stepId,
|
|
60
|
+
command: 'end-session',
|
|
61
|
+
}
|
|
62
|
+
: null;
|
|
63
|
+
captureStepSnapshotBestEffort({
|
|
64
|
+
session,
|
|
65
|
+
step: endSessionStepHandle,
|
|
66
|
+
phase: 'before',
|
|
67
|
+
pageRef: session.runtime?.currentPageRef,
|
|
68
|
+
});
|
|
69
|
+
appendCommandLifecycleEventBestEffort({
|
|
70
|
+
step: endSessionStepHandle,
|
|
71
|
+
phase: 'started',
|
|
72
|
+
attributes: {
|
|
73
|
+
hasWorkflowSession: Boolean(session.intentSessionId),
|
|
74
|
+
currentRequestId: session.currentRequestId ?? null,
|
|
75
|
+
pageRef: session.runtime?.currentPageRef,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
return withApiTraceContext({
|
|
79
|
+
runId: session.activeRunId,
|
|
80
|
+
stepId: endSessionStep?.stepId,
|
|
81
|
+
command: 'end-session',
|
|
82
|
+
}, async () => {
|
|
83
|
+
const remoteCompletion = await completeWorkflowSessionRemote({
|
|
84
|
+
session,
|
|
85
|
+
stepId: endSessionStep?.stepId,
|
|
86
|
+
command: 'end-session',
|
|
87
|
+
terminalStatus: 'completed',
|
|
88
|
+
runStatus: 'completed',
|
|
89
|
+
summary: 'Workflow session completed.',
|
|
90
|
+
outcomeType: 'workflow_session_completed',
|
|
91
|
+
message: 'Workflow session completed.',
|
|
92
|
+
});
|
|
93
|
+
if (!remoteCompletion.success) {
|
|
94
|
+
const outcomeType = remoteCompletion.error === 'backend_session_complete_failed' ? 'backend_session_complete_failed' : 'blocked';
|
|
95
|
+
appendCommandLifecycleEventBestEffort({
|
|
96
|
+
step: endSessionStepHandle,
|
|
97
|
+
phase: 'failed',
|
|
98
|
+
attributes: {
|
|
99
|
+
outcomeType,
|
|
100
|
+
reason: remoteCompletion.reason,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
finalizeEndSessionStepBestEffort(session.activeRunId, endSessionStep?.stepId, {
|
|
104
|
+
success: false,
|
|
105
|
+
outcomeType,
|
|
106
|
+
message: 'Workflow session end failed.',
|
|
107
|
+
reason: remoteCompletion.reason,
|
|
108
|
+
});
|
|
109
|
+
await exportRunStepToOtlpHttpJsonBestEffort(session.activeRunId, endSessionStep?.stepId);
|
|
110
|
+
return {
|
|
111
|
+
success: false,
|
|
112
|
+
error: remoteCompletion.error,
|
|
113
|
+
outcomeType: remoteCompletion.error === 'backend_session_complete_failed' ? 'failed' : 'blocked',
|
|
114
|
+
message: 'Workflow session end failed.',
|
|
115
|
+
reason: remoteCompletion.reason,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
captureStepSnapshotBestEffort({
|
|
119
|
+
session,
|
|
120
|
+
step: endSessionStepHandle,
|
|
121
|
+
phase: 'after',
|
|
122
|
+
pageRef: session.runtime?.currentPageRef,
|
|
123
|
+
});
|
|
124
|
+
appendCommandLifecycleEventBestEffort({
|
|
125
|
+
step: endSessionStepHandle,
|
|
126
|
+
phase: 'completed',
|
|
127
|
+
attributes: {
|
|
128
|
+
outcomeType: 'workflow_session_completed',
|
|
129
|
+
intentSessionId: remoteCompletion.response.session.id,
|
|
130
|
+
remoteLastEventSeq: remoteCompletion.response.session.last_event_seq,
|
|
131
|
+
pageRef: session.runtime?.currentPageRef,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
finalizeEndSessionStepBestEffort(remoteCompletion.runId, remoteCompletion.stepId ?? undefined, {
|
|
135
|
+
success: true,
|
|
136
|
+
outcomeType: 'workflow_session_completed',
|
|
137
|
+
message: 'Workflow session completed.',
|
|
138
|
+
});
|
|
139
|
+
finalizeRunRecordBestEffort(remoteCompletion.runId, {
|
|
140
|
+
status: 'completed',
|
|
141
|
+
success: true,
|
|
142
|
+
outcomeType: 'workflow_session_completed',
|
|
143
|
+
message: 'Workflow session completed.',
|
|
144
|
+
});
|
|
145
|
+
const nextSession = clearWorkflowState(session);
|
|
146
|
+
saveSession(nextSession);
|
|
147
|
+
await exportRunStepToOtlpHttpJsonBestEffort(remoteCompletion.runId, remoteCompletion.stepId ?? undefined);
|
|
148
|
+
await exportRunRootToOtlpHttpJsonBestEffort(remoteCompletion.runId);
|
|
149
|
+
return {
|
|
150
|
+
success: true,
|
|
151
|
+
runId: remoteCompletion.runId,
|
|
152
|
+
intentSessionId: remoteCompletion.response.session.id,
|
|
153
|
+
status: remoteCompletion.response.session.status,
|
|
154
|
+
lastEventSeq: remoteCompletion.response.session.last_event_seq,
|
|
155
|
+
browserSessionId: remoteCompletion.response.browser_session_id,
|
|
156
|
+
completedAt: remoteCompletion.completedAt,
|
|
157
|
+
outcomeType: 'workflow_session_completed',
|
|
158
|
+
message: 'Workflow session completed.',
|
|
159
|
+
};
|
|
160
|
+
});
|
|
161
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { extract as runExtract } from '@browserbasehq/stagehand/lib/inference.js';
|
|
2
2
|
import { v3Logger } from '@browserbasehq/stagehand/lib/v3/logger.js';
|
|
3
3
|
import { captureHybridSnapshot } from '@browserbasehq/stagehand/lib/v3/understudy/a11y/snapshot/index.js';
|
|
4
|
-
import { incrementMetric, recordLlmUsage, recordPayloadBudget } from '../runtime-
|
|
4
|
+
import { incrementMetric, recordLlmUsage, recordPayloadBudget } from '../runtime-metrics.js';
|
|
5
5
|
import { stagehandRuntimeResolution } from '../runtime-resolution.js';
|
|
6
6
|
import { withStagehand } from '../stagehand-runtime.js';
|
|
7
7
|
import { readLocatorOuterHtml } from './descriptor-validation.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAyUnD,wBAAsB,OAAO,CAC3B,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CA8Sf"}
|