@nuanu-ai/agentbrowse 0.2.46 → 0.2.48
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 +69 -10
- package/dist/agentpay-gateway.d.ts +9 -0
- package/dist/agentpay-gateway.d.ts.map +1 -1
- package/dist/agentpay-gateway.js +30 -0
- 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/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 +0 -2
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +109 -17
- 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 +50 -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/index.d.ts.map +1 -1
- package/dist/index.js +144 -45
- 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/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 +9 -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
|
@@ -1,39 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* browse fill-secret <fillRef> <
|
|
3
|
-
*
|
|
2
|
+
* browse fill-secret <fillRef> <requestId> — Claim an already approved secret request and fill
|
|
3
|
+
* protected fields using deterministic browser execution.
|
|
4
4
|
*/
|
|
5
5
|
import { outputFailure, outputJSON } from '../output.js';
|
|
6
|
-
import { getFillableForm,
|
|
7
|
-
import { deleteCachedTransientSecret, getCachedTransientSecret, saveSession } from '../session.js';
|
|
6
|
+
import { getFillableForm, getSecretRequestSnapshot, saveProtectedExposure, saveSecretRequestSnapshot, } from '../runtime-protected-state.js';
|
|
8
7
|
import { connectPlaywright, disconnectPlaywright, resolvePageByRef, syncSessionPage, } from '../playwright-runtime.js';
|
|
8
|
+
import { finishRunStep, startRunStep } from '../run-store.js';
|
|
9
|
+
import { exportRunStepToOtlpHttpJsonBestEffort } from '../otel-exporter.js';
|
|
10
|
+
import { appendCommandLifecycleEventBestEffort, captureStepSnapshotBestEffort, } from '../run-observability.js';
|
|
11
|
+
import { saveSession } from '../session.js';
|
|
9
12
|
import { tryResolveCatalogHost } from '../secrets/catalog-sync.js';
|
|
10
|
-
import {
|
|
13
|
+
import { describeSecretRequestStatus, serializeSecretRequestContext, } from '../secrets/request-output.js';
|
|
11
14
|
import { executeProtectedFill } from '../secrets/protected-fill.js';
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
import { getSecretBackend } from '../secrets/backend.js';
|
|
16
|
+
import { AgentpayRequestError } from '../sessions-backend.js';
|
|
17
|
+
function persistRequestSnapshot(session, snapshot) {
|
|
18
|
+
const persisted = saveSecretRequestSnapshot(session, snapshot);
|
|
14
19
|
saveSession(session);
|
|
15
20
|
return persisted;
|
|
16
21
|
}
|
|
17
|
-
function
|
|
18
|
-
const current =
|
|
22
|
+
function markRequestClaimed(session, requestId, claimedAt) {
|
|
23
|
+
const current = getSecretRequestSnapshot(session, requestId);
|
|
19
24
|
if (!current) {
|
|
20
|
-
throw new Error('
|
|
25
|
+
throw new Error('secret_request_not_found');
|
|
21
26
|
}
|
|
22
|
-
if (
|
|
23
|
-
|
|
27
|
+
if (session.currentRequestId === requestId) {
|
|
28
|
+
session.currentRequestId = undefined;
|
|
29
|
+
session.lastKnownStatus = 'in_progress';
|
|
24
30
|
}
|
|
25
|
-
return
|
|
31
|
+
return persistRequestSnapshot(session, {
|
|
26
32
|
...current,
|
|
27
|
-
|
|
28
|
-
|
|
33
|
+
claimedAt,
|
|
34
|
+
updatedAt: claimedAt,
|
|
29
35
|
});
|
|
30
36
|
}
|
|
31
|
-
function activateProtectedExposure(session, fillableForm,
|
|
37
|
+
function activateProtectedExposure(session, fillableForm, requestId, reason) {
|
|
32
38
|
saveProtectedExposure(session, {
|
|
33
39
|
pageRef: fillableForm.pageRef,
|
|
34
40
|
scopeRef: fillableForm.scopeRef,
|
|
35
41
|
fillRef: fillableForm.fillRef,
|
|
36
|
-
|
|
42
|
+
requestId: requestId,
|
|
37
43
|
activatedAt: new Date().toISOString(),
|
|
38
44
|
reason,
|
|
39
45
|
});
|
|
@@ -53,319 +59,498 @@ function restrictFormToCandidateFields(fillableForm, storedSecretCandidate) {
|
|
|
53
59
|
fields: filteredFields,
|
|
54
60
|
};
|
|
55
61
|
}
|
|
56
|
-
function
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
case 'confirmation':
|
|
62
|
-
return 'wait-for-approval';
|
|
63
|
-
case 'denied':
|
|
64
|
-
return 'ask-user';
|
|
65
|
-
case 'timed_out':
|
|
66
|
-
case 'completed':
|
|
67
|
-
return 'ask-user';
|
|
68
|
-
default:
|
|
69
|
-
return 'ask-user';
|
|
70
|
-
}
|
|
62
|
+
function withFillableFormPresence(fillableForm, payload) {
|
|
63
|
+
return {
|
|
64
|
+
...payload,
|
|
65
|
+
fillableFormPresence: fillableForm.presence ?? 'present',
|
|
66
|
+
};
|
|
71
67
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
case 'checking':
|
|
76
|
-
case 'notify':
|
|
77
|
-
case 'confirmation':
|
|
78
|
-
return 'Protected fill is waiting for user approval in AgentPay Cabinet.';
|
|
79
|
-
case 'denied':
|
|
80
|
-
return 'Protected fill is blocked because the user denied this intent in AgentPay Cabinet.';
|
|
81
|
-
case 'timed_out':
|
|
82
|
-
case 'completed':
|
|
83
|
-
return 'Protected fill requires a new intent because this intent is no longer usable.';
|
|
84
|
-
default:
|
|
85
|
-
return 'Protected fill cannot continue because the intent is not approved.';
|
|
68
|
+
function finalizeFillSecretStepBestEffort(runId, stepId, options) {
|
|
69
|
+
if (!runId || !stepId) {
|
|
70
|
+
return;
|
|
86
71
|
}
|
|
72
|
+
try {
|
|
73
|
+
finishRunStep({
|
|
74
|
+
runId,
|
|
75
|
+
stepId,
|
|
76
|
+
...options,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function emitFillSecretFailure(session, runId, stepId, payload, options = {}) {
|
|
83
|
+
const step = runId && stepId ? { runId, stepId, command: 'fill-secret' } : null;
|
|
84
|
+
captureStepSnapshotBestEffort({
|
|
85
|
+
session,
|
|
86
|
+
step,
|
|
87
|
+
phase: 'point-in-time',
|
|
88
|
+
pageRef: options.pageRef ?? session.runtime?.currentPageRef,
|
|
89
|
+
});
|
|
90
|
+
appendCommandLifecycleEventBestEffort({
|
|
91
|
+
step,
|
|
92
|
+
phase: 'failed',
|
|
93
|
+
attributes: {
|
|
94
|
+
outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : payload.error,
|
|
95
|
+
pageRef: options.pageRef,
|
|
96
|
+
fillRef: options.fillRef,
|
|
97
|
+
requestId: options.requestId,
|
|
98
|
+
reason: typeof payload.reason === 'string' ? payload.reason : payload.error,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
finalizeFillSecretStepBestEffort(runId, stepId, {
|
|
102
|
+
success: false,
|
|
103
|
+
outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : payload.error,
|
|
104
|
+
message: typeof payload.message === 'string' ? payload.message : payload.error,
|
|
105
|
+
reason: typeof payload.reason === 'string' ? payload.reason : payload.error,
|
|
106
|
+
});
|
|
107
|
+
await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
|
|
108
|
+
return outputFailure(payload);
|
|
87
109
|
}
|
|
88
|
-
function
|
|
89
|
-
|
|
110
|
+
async function emitFillSecretSuccess(session, runId, stepId, payload, options = {}) {
|
|
111
|
+
const step = runId && stepId ? { runId, stepId, command: 'fill-secret' } : null;
|
|
112
|
+
captureStepSnapshotBestEffort({
|
|
113
|
+
session,
|
|
114
|
+
step,
|
|
115
|
+
phase: 'after',
|
|
116
|
+
pageRef: options.pageRef ?? session.runtime?.currentPageRef,
|
|
117
|
+
});
|
|
118
|
+
appendCommandLifecycleEventBestEffort({
|
|
119
|
+
step,
|
|
120
|
+
phase: 'completed',
|
|
121
|
+
attributes: {
|
|
122
|
+
outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : 'protected_fill_completed',
|
|
123
|
+
pageRef: options.pageRef,
|
|
124
|
+
fillRef: options.fillRef,
|
|
125
|
+
requestId: options.requestId,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
finalizeFillSecretStepBestEffort(runId, stepId, {
|
|
129
|
+
success: true,
|
|
130
|
+
outcomeType: typeof payload.outcomeType === 'string' ? payload.outcomeType : 'protected_fill_completed',
|
|
131
|
+
message: typeof payload.message === 'string' ? payload.message : 'Protected fill completed.',
|
|
132
|
+
reason: typeof payload.reason === 'string' ? payload.reason : undefined,
|
|
133
|
+
});
|
|
134
|
+
await exportRunStepToOtlpHttpJsonBestEffort(runId, stepId);
|
|
135
|
+
return outputJSON(payload);
|
|
136
|
+
}
|
|
137
|
+
function parseClaimFailure(error) {
|
|
138
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
139
|
+
if (message.includes('not approved yet') ||
|
|
140
|
+
message.includes('secret_request_not_fulfilled') ||
|
|
141
|
+
message.includes('does not have resolved secret values yet')) {
|
|
142
|
+
return 'not_fulfilled';
|
|
143
|
+
}
|
|
144
|
+
if (message.includes('already claimed') || message.includes('secret_request_already_claimed')) {
|
|
145
|
+
return 'already_claimed';
|
|
146
|
+
}
|
|
147
|
+
return 'other';
|
|
90
148
|
}
|
|
91
|
-
function
|
|
92
|
-
|
|
149
|
+
function failureForUnfulfilledRequest(fillableForm, request, fillRef, requestId) {
|
|
150
|
+
const statusContract = describeSecretRequestStatus(request.status, request.requestType);
|
|
151
|
+
return withFillableFormPresence(fillableForm, {
|
|
152
|
+
error: 'secret_request_not_ready',
|
|
153
|
+
...(statusContract.outcomeType ? { outcomeType: statusContract.outcomeType } : {}),
|
|
154
|
+
message: request.status === 'pending'
|
|
155
|
+
? 'Protected fill is waiting for user approval in AgentPay.'
|
|
156
|
+
: statusContract.message,
|
|
157
|
+
reason: statusContract.reason,
|
|
158
|
+
fillRef,
|
|
159
|
+
requestId,
|
|
160
|
+
...serializeSecretRequestContext(request),
|
|
161
|
+
requestStatus: request.status,
|
|
162
|
+
nextAction: statusContract.nextAction ?? 'poll-secret',
|
|
163
|
+
});
|
|
93
164
|
}
|
|
94
|
-
export async function fillSecret(session, fillRef,
|
|
165
|
+
export async function fillSecret(session, fillRef, requestId) {
|
|
166
|
+
const fillSecretStep = session.activeRunId
|
|
167
|
+
? startRunStep({
|
|
168
|
+
runId: session.activeRunId,
|
|
169
|
+
command: 'fill-secret',
|
|
170
|
+
refs: {
|
|
171
|
+
fillRef,
|
|
172
|
+
requestId,
|
|
173
|
+
},
|
|
174
|
+
protectedStep: true,
|
|
175
|
+
})
|
|
176
|
+
: null;
|
|
177
|
+
const fillSecretStepHandle = session.activeRunId && fillSecretStep?.stepId
|
|
178
|
+
? {
|
|
179
|
+
runId: session.activeRunId,
|
|
180
|
+
stepId: fillSecretStep.stepId,
|
|
181
|
+
command: 'fill-secret',
|
|
182
|
+
}
|
|
183
|
+
: null;
|
|
184
|
+
captureStepSnapshotBestEffort({
|
|
185
|
+
session,
|
|
186
|
+
step: fillSecretStepHandle,
|
|
187
|
+
phase: 'before',
|
|
188
|
+
pageRef: session.runtime?.currentPageRef,
|
|
189
|
+
});
|
|
190
|
+
appendCommandLifecycleEventBestEffort({
|
|
191
|
+
step: fillSecretStepHandle,
|
|
192
|
+
phase: 'started',
|
|
193
|
+
attributes: {
|
|
194
|
+
fillRef,
|
|
195
|
+
requestId,
|
|
196
|
+
pageRef: session.runtime?.currentPageRef,
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
if (!session.intentSessionId) {
|
|
200
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, {
|
|
201
|
+
error: 'workflow_session_unavailable',
|
|
202
|
+
outcomeType: 'blocked',
|
|
203
|
+
message: 'Protected fill was not started because no active workflow session is bound to this browser.',
|
|
204
|
+
reason: 'Run start-session first so AgentBrowse has a workflow session for secret requests.',
|
|
205
|
+
fillRef,
|
|
206
|
+
requestId,
|
|
207
|
+
}, {
|
|
208
|
+
fillRef,
|
|
209
|
+
requestId,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
95
212
|
const fillableForm = getFillableForm(session, fillRef);
|
|
96
213
|
if (!fillableForm) {
|
|
97
|
-
return
|
|
214
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, {
|
|
98
215
|
error: 'unknown_fill_ref',
|
|
99
216
|
outcomeType: 'blocked',
|
|
100
217
|
message: 'Protected fill was not started because the requested fill reference is unknown.',
|
|
101
218
|
reason: 'The provided fillRef does not match any currently observed protected fill target.',
|
|
102
219
|
fillRef,
|
|
103
|
-
|
|
220
|
+
requestId,
|
|
221
|
+
}, {
|
|
222
|
+
fillRef,
|
|
223
|
+
requestId,
|
|
104
224
|
});
|
|
105
225
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
error: 'secret_intent_not_found',
|
|
226
|
+
if (fillableForm.presence === 'absent') {
|
|
227
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, withFillableFormPresence(fillableForm, {
|
|
228
|
+
error: 'fillable_form_absent',
|
|
110
229
|
outcomeType: 'blocked',
|
|
111
|
-
message: 'Protected fill was not started because the requested
|
|
112
|
-
reason: '
|
|
230
|
+
message: 'Protected fill was not started because the requested fill target is no longer present on the page.',
|
|
231
|
+
reason: 'AgentBrowse already observed this protected fill target as absent, so a new observe pass is required before protected fill can continue.',
|
|
232
|
+
fillRef,
|
|
233
|
+
requestId,
|
|
234
|
+
}), {
|
|
235
|
+
pageRef: fillableForm.pageRef,
|
|
113
236
|
fillRef,
|
|
114
|
-
|
|
237
|
+
requestId,
|
|
115
238
|
});
|
|
116
239
|
}
|
|
117
|
-
const
|
|
118
|
-
if (
|
|
119
|
-
return
|
|
120
|
-
error: '
|
|
240
|
+
const request = getSecretRequestSnapshot(session, requestId);
|
|
241
|
+
if (!request) {
|
|
242
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, {
|
|
243
|
+
error: 'secret_request_not_found',
|
|
121
244
|
outcomeType: 'blocked',
|
|
122
|
-
message: 'Protected fill was
|
|
123
|
-
reason:
|
|
245
|
+
message: 'Protected fill was not started because the requested secret request does not exist.',
|
|
246
|
+
reason: 'Run request-secret and poll-secret first so AgentBrowse has the latest request state.',
|
|
124
247
|
fillRef,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
intentStatus: latestIntent.status,
|
|
129
|
-
nextAction: 'reobserve',
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
if (!(latestIntent.status === 'approved' || latestIntent.status === 'completed')) {
|
|
133
|
-
return outputFailure({
|
|
134
|
-
error: 'secret_intent_not_approved',
|
|
135
|
-
...(outcomeTypeForNonApprovedIntent(latestIntent.status)
|
|
136
|
-
? { outcomeType: outcomeTypeForNonApprovedIntent(latestIntent.status) }
|
|
137
|
-
: {}),
|
|
138
|
-
message: messageForNonApprovedIntent(latestIntent.status),
|
|
139
|
-
reason: reasonForNonApprovedIntent(latestIntent.status),
|
|
248
|
+
requestId,
|
|
249
|
+
}, {
|
|
250
|
+
pageRef: fillableForm.pageRef,
|
|
140
251
|
fillRef,
|
|
141
|
-
|
|
142
|
-
...serializeSecretIntentContext(latestIntent),
|
|
143
|
-
intentStatus: latestIntent.status,
|
|
144
|
-
nextAction: nextActionForNonApprovedIntent(latestIntent.status),
|
|
252
|
+
requestId,
|
|
145
253
|
});
|
|
146
254
|
}
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
: 'Run poll-intent after approval so AgentBrowse can cache the transient protected values before fill-secret.';
|
|
152
|
-
const missingCacheNextAction = latestIntent.status === 'completed' ? 'ask-user' : 'poll-intent';
|
|
153
|
-
const missingCacheMessage = latestIntent.status === 'completed'
|
|
154
|
-
? 'Protected fill could not continue because the one-time secret payload is no longer cached in the current session.'
|
|
155
|
-
: 'Protected fill could not continue because the approved secret payload is not cached in the current session.';
|
|
156
|
-
return outputFailure({
|
|
157
|
-
error: 'transient_secret_not_cached',
|
|
255
|
+
const latestRequest = persistRequestSnapshot(session, request);
|
|
256
|
+
if (latestRequest.fillRef !== fillRef) {
|
|
257
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, withFillableFormPresence(fillableForm, {
|
|
258
|
+
error: 'secret_request_fill_mismatch',
|
|
158
259
|
outcomeType: 'blocked',
|
|
159
|
-
message:
|
|
160
|
-
reason:
|
|
260
|
+
message: 'Protected fill was blocked because the approved secret request belongs to a different fill target.',
|
|
261
|
+
reason: `The approved request belongs to fillRef ${latestRequest.fillRef}, not ${fillRef}.`,
|
|
262
|
+
fillRef,
|
|
263
|
+
requestId,
|
|
264
|
+
...serializeSecretRequestContext(latestRequest),
|
|
265
|
+
requestFillRef: latestRequest.fillRef,
|
|
266
|
+
requestStatus: latestRequest.status,
|
|
267
|
+
nextAction: 'reobserve',
|
|
268
|
+
}), {
|
|
269
|
+
pageRef: fillableForm.pageRef,
|
|
161
270
|
fillRef,
|
|
162
|
-
|
|
163
|
-
...serializeSecretIntentContext(latestIntent),
|
|
164
|
-
intentStatus: latestIntent.status,
|
|
165
|
-
nextAction: missingCacheNextAction,
|
|
271
|
+
requestId,
|
|
166
272
|
});
|
|
167
273
|
}
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
saveSession(session);
|
|
172
|
-
return outputFailure({
|
|
173
|
-
error: 'transient_secret_context_mismatch',
|
|
274
|
+
if (latestRequest.claimedAt) {
|
|
275
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, withFillableFormPresence(fillableForm, {
|
|
276
|
+
error: 'secret_request_already_claimed',
|
|
174
277
|
outcomeType: 'blocked',
|
|
175
|
-
message: 'Protected fill
|
|
176
|
-
reason: '
|
|
278
|
+
message: 'Protected fill could not continue because this one-time secret request was already claimed earlier.',
|
|
279
|
+
reason: 'Secret values can only be claimed once for this request, so AgentBrowse needs a new request before it can fill again.',
|
|
280
|
+
fillRef,
|
|
281
|
+
requestId,
|
|
282
|
+
...serializeSecretRequestContext(latestRequest),
|
|
283
|
+
requestStatus: latestRequest.status,
|
|
284
|
+
nextAction: 'request-secret',
|
|
285
|
+
}), {
|
|
286
|
+
pageRef: fillableForm.pageRef,
|
|
177
287
|
fillRef,
|
|
178
|
-
|
|
179
|
-
...serializeSecretIntentContext(latestIntent),
|
|
180
|
-
intentStatus: latestIntent.status,
|
|
181
|
-
nextAction: 'poll-intent',
|
|
288
|
+
requestId,
|
|
182
289
|
});
|
|
183
290
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
catch (error) {
|
|
189
|
-
deleteCachedTransientSecret(session, intentId);
|
|
190
|
-
saveSession(session);
|
|
191
|
-
return outputFailure({
|
|
192
|
-
error: 'browser_connection_failed',
|
|
193
|
-
message: 'Protected fill could not connect to the browser.',
|
|
291
|
+
if (latestRequest.status !== 'fulfilled') {
|
|
292
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, failureForUnfulfilledRequest(fillableForm, latestRequest, fillRef, requestId), {
|
|
293
|
+
pageRef: fillableForm.pageRef,
|
|
194
294
|
fillRef,
|
|
195
|
-
|
|
196
|
-
...serializeSecretIntentContext(latestIntent),
|
|
197
|
-
reason: error instanceof Error ? error.message : String(error),
|
|
295
|
+
requestId,
|
|
198
296
|
});
|
|
199
297
|
}
|
|
200
|
-
|
|
298
|
+
let browser = null;
|
|
201
299
|
let finalResult = null;
|
|
202
300
|
try {
|
|
203
|
-
|
|
301
|
+
browser = await connectPlaywright(session.cdpUrl);
|
|
302
|
+
const page = await resolvePageByRef(browser, session, fillableForm.pageRef);
|
|
204
303
|
const syncedPage = await syncSessionPage(session, fillableForm.pageRef, page);
|
|
205
304
|
const observedHost = tryResolveCatalogHost(syncedPage.url);
|
|
206
305
|
const contextMismatchReasons = [];
|
|
207
|
-
if (
|
|
306
|
+
if (latestRequest.host && observedHost && latestRequest.host !== observedHost) {
|
|
208
307
|
contextMismatchReasons.push('host');
|
|
209
308
|
}
|
|
210
|
-
if (
|
|
309
|
+
if (latestRequest.scopeRef && latestRequest.scopeRef !== fillableForm.scopeRef) {
|
|
211
310
|
contextMismatchReasons.push('scope');
|
|
212
311
|
}
|
|
213
312
|
if (contextMismatchReasons.length > 0) {
|
|
214
|
-
const completedIntent = completeIntent(session, intentId);
|
|
215
313
|
finalResult = {
|
|
216
314
|
success: false,
|
|
217
|
-
payload: {
|
|
218
|
-
error: '
|
|
315
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
316
|
+
error: 'secret_request_context_mismatch',
|
|
219
317
|
outcomeType: 'blocked',
|
|
220
|
-
message: 'Protected fill was blocked because the page or protected surface no longer matches the approved
|
|
221
|
-
reason: 'The current page host or protected surface no longer matches the context that was approved for this
|
|
318
|
+
message: 'Protected fill was blocked because the page or protected surface no longer matches the approved request context.',
|
|
319
|
+
reason: 'The current page host or protected surface no longer matches the context that was approved for this request.',
|
|
222
320
|
fillRef,
|
|
223
|
-
|
|
224
|
-
...
|
|
225
|
-
|
|
321
|
+
requestId,
|
|
322
|
+
...serializeSecretRequestContext(latestRequest),
|
|
323
|
+
requestStatus: latestRequest.status,
|
|
226
324
|
nextAction: 'reobserve',
|
|
227
|
-
|
|
325
|
+
requestReusable: true,
|
|
228
326
|
mismatchReasons: contextMismatchReasons,
|
|
229
|
-
...(
|
|
327
|
+
...(latestRequest.host ? { expectedHost: latestRequest.host } : {}),
|
|
230
328
|
...(observedHost ? { observedHost } : {}),
|
|
231
|
-
...(
|
|
329
|
+
...(latestRequest.scopeRef ? { expectedScopeRef: latestRequest.scopeRef } : {}),
|
|
232
330
|
...(fillableForm.scopeRef ? { observedScopeRef: fillableForm.scopeRef } : {}),
|
|
233
|
-
},
|
|
331
|
+
}),
|
|
234
332
|
};
|
|
235
333
|
}
|
|
236
334
|
else {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
335
|
+
let claimedAt = new Date().toISOString();
|
|
336
|
+
let claimStoredSecretRef = latestRequest.storedSecretRef;
|
|
337
|
+
let claimKind = latestRequest.kind;
|
|
338
|
+
let protectedValues = null;
|
|
240
339
|
try {
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
activateProtectedExposure(session, fillableForm, intentId, 'protected_fill_success');
|
|
340
|
+
const claim = await getSecretBackend().claimSecretRequest(session.intentSessionId, requestId, fillSecretStep?.stepId ?? `claim-${Date.now()}`);
|
|
341
|
+
claimedAt = claim.issuedAt;
|
|
342
|
+
claimStoredSecretRef = claim.secret.storedSecretRef ?? claimStoredSecretRef;
|
|
343
|
+
claimKind = claim.secret.kind ?? claimKind;
|
|
344
|
+
protectedValues = { ...claim.secret.values };
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
const parsed = parseClaimFailure(error);
|
|
348
|
+
if (parsed === 'not_fulfilled') {
|
|
251
349
|
finalResult = {
|
|
252
|
-
success:
|
|
253
|
-
payload:
|
|
254
|
-
fillRef,
|
|
255
|
-
intentId,
|
|
256
|
-
...serializeSecretIntentContext(completedIntent),
|
|
257
|
-
filledFields: execution.filledFields,
|
|
258
|
-
intentStatus: completedIntent.status,
|
|
259
|
-
message: 'Protected fill completed successfully.',
|
|
260
|
-
reason: 'AgentBrowse filled the protected fields using the one-time secret payload.',
|
|
261
|
-
},
|
|
350
|
+
success: false,
|
|
351
|
+
payload: failureForUnfulfilledRequest(fillableForm, latestRequest, fillRef, requestId),
|
|
262
352
|
};
|
|
263
353
|
}
|
|
264
|
-
else if (
|
|
265
|
-
const completedIntent = completeIntent(session, intentId);
|
|
266
|
-
activateProtectedExposure(session, fillableForm, intentId, 'protected_fill_binding_stale');
|
|
354
|
+
else if (parsed === 'already_claimed') {
|
|
267
355
|
finalResult = {
|
|
268
356
|
success: false,
|
|
269
|
-
payload: {
|
|
270
|
-
error: '
|
|
271
|
-
outcomeType: '
|
|
272
|
-
message: 'Protected fill
|
|
357
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
358
|
+
error: 'secret_request_already_claimed',
|
|
359
|
+
outcomeType: 'blocked',
|
|
360
|
+
message: 'Protected fill could not continue because this one-time secret request was already claimed earlier.',
|
|
361
|
+
reason: 'Secret values can only be claimed once for this request, so AgentBrowse needs a new request before it can fill again.',
|
|
273
362
|
fillRef,
|
|
274
|
-
|
|
275
|
-
...
|
|
276
|
-
|
|
277
|
-
nextAction: '
|
|
278
|
-
|
|
279
|
-
fieldKeys: execution.fieldKeys,
|
|
280
|
-
reason: execution.reason,
|
|
281
|
-
attempts: execution.attempts,
|
|
282
|
-
},
|
|
363
|
+
requestId,
|
|
364
|
+
...serializeSecretRequestContext(latestRequest),
|
|
365
|
+
requestStatus: latestRequest.status,
|
|
366
|
+
nextAction: 'request-secret',
|
|
367
|
+
}),
|
|
283
368
|
};
|
|
284
369
|
}
|
|
285
|
-
else
|
|
286
|
-
const completedIntent = completeIntent(session, intentId);
|
|
287
|
-
activateProtectedExposure(session, fillableForm, intentId, 'protected_fill_validation_failed');
|
|
370
|
+
else {
|
|
288
371
|
finalResult = {
|
|
289
372
|
success: false,
|
|
290
|
-
payload: {
|
|
291
|
-
error: '
|
|
373
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
374
|
+
error: 'secret_claim_failed',
|
|
292
375
|
outcomeType: 'blocked',
|
|
293
|
-
message: 'Protected fill
|
|
294
|
-
reason:
|
|
376
|
+
message: 'Protected fill could not continue because AgentBrowse failed to claim the one-time secret payload.',
|
|
377
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
295
378
|
fillRef,
|
|
296
|
-
|
|
297
|
-
...
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
manualOverrideAllowed: true,
|
|
302
|
-
filledFields: execution.filledFields,
|
|
303
|
-
fieldErrors: execution.fieldErrors,
|
|
304
|
-
},
|
|
379
|
+
requestId,
|
|
380
|
+
...serializeSecretRequestContext(latestRequest),
|
|
381
|
+
requestStatus: latestRequest.status,
|
|
382
|
+
nextAction: error instanceof AgentpayRequestError && error.status === 404 ? 'poll-secret' : 'ask-user',
|
|
383
|
+
}),
|
|
305
384
|
};
|
|
306
385
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
386
|
+
}
|
|
387
|
+
if (!finalResult) {
|
|
388
|
+
if (!protectedValues) {
|
|
389
|
+
throw new Error('claimed_secret_values_missing');
|
|
390
|
+
}
|
|
391
|
+
const claimedRequest = markRequestClaimed(session, requestId, claimedAt);
|
|
392
|
+
if (claimStoredSecretRef || claimKind) {
|
|
393
|
+
persistRequestSnapshot(session, {
|
|
394
|
+
...claimedRequest,
|
|
395
|
+
...(claimStoredSecretRef ? { storedSecretRef: claimStoredSecretRef } : {}),
|
|
396
|
+
...(claimKind ? { kind: claimKind } : {}),
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
const storedSecretCandidate = fillableForm.storedSecretCandidates.find((candidate) => candidate.storedSecretRef === (claimStoredSecretRef ?? latestRequest.storedSecretRef));
|
|
400
|
+
const executableForm = restrictFormToCandidateFields(fillableForm, storedSecretCandidate);
|
|
401
|
+
try {
|
|
402
|
+
const execution = await executeProtectedFill({
|
|
403
|
+
session,
|
|
404
|
+
page,
|
|
405
|
+
fillableForm: executableForm,
|
|
406
|
+
protectedValues,
|
|
407
|
+
fieldPolicies: storedSecretCandidate?.fieldPolicies,
|
|
408
|
+
});
|
|
409
|
+
if (execution.kind === 'success') {
|
|
410
|
+
activateProtectedExposure(session, fillableForm, requestId, 'protected_fill_success');
|
|
411
|
+
finalResult = {
|
|
412
|
+
success: true,
|
|
413
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
414
|
+
fillRef,
|
|
415
|
+
requestId,
|
|
416
|
+
...serializeSecretRequestContext(getSecretRequestSnapshot(session, requestId)),
|
|
417
|
+
filledFields: execution.filledFields,
|
|
418
|
+
requestStatus: latestRequest.status,
|
|
419
|
+
message: 'Protected fill completed successfully.',
|
|
420
|
+
reason: 'AgentBrowse filled the protected fields using the claimed one-time secret payload.',
|
|
421
|
+
}),
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
else if (execution.kind === 'binding_stale') {
|
|
425
|
+
activateProtectedExposure(session, fillableForm, requestId, 'protected_fill_binding_stale');
|
|
426
|
+
finalResult = {
|
|
427
|
+
success: false,
|
|
428
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
429
|
+
error: 'secret_fill_binding_stale',
|
|
430
|
+
outcomeType: 'binding_stale',
|
|
431
|
+
message: 'Protected fill was blocked because the stored field bindings are no longer valid on the page.',
|
|
432
|
+
fillRef,
|
|
433
|
+
requestId,
|
|
434
|
+
...serializeSecretRequestContext(getSecretRequestSnapshot(session, requestId)),
|
|
435
|
+
requestStatus: latestRequest.status,
|
|
436
|
+
nextAction: 'reobserve',
|
|
437
|
+
requestReusable: false,
|
|
438
|
+
targetRef: execution.targetRef,
|
|
439
|
+
fieldKeys: execution.fieldKeys,
|
|
440
|
+
reason: execution.reason,
|
|
441
|
+
attempts: execution.attempts,
|
|
442
|
+
}),
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
else if (execution.kind === 'validation_failed') {
|
|
446
|
+
activateProtectedExposure(session, fillableForm, requestId, 'protected_fill_validation_failed');
|
|
447
|
+
finalResult = {
|
|
448
|
+
success: false,
|
|
449
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
450
|
+
error: 'secret_validation_failed',
|
|
451
|
+
outcomeType: 'blocked',
|
|
452
|
+
message: 'Protected fill stopped because the stored data did not pass client-side validation.',
|
|
453
|
+
reason: 'Protected execution reported client-side validation errors for one or more filled fields.',
|
|
454
|
+
fillRef,
|
|
455
|
+
requestId,
|
|
456
|
+
...serializeSecretRequestContext(getSecretRequestSnapshot(session, requestId)),
|
|
457
|
+
requestStatus: latestRequest.status,
|
|
458
|
+
executionResult: 'validation_failed',
|
|
459
|
+
nextAction: 'ask-user',
|
|
460
|
+
manualOverrideAllowed: true,
|
|
461
|
+
requestReusable: false,
|
|
462
|
+
filledFields: execution.filledFields,
|
|
463
|
+
fieldErrors: execution.fieldErrors,
|
|
464
|
+
}),
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
activateProtectedExposure(session, fillableForm, requestId, 'protected_fill_unexpected_error');
|
|
469
|
+
finalResult = {
|
|
470
|
+
success: false,
|
|
471
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
472
|
+
error: 'protected_fill_execution_failed',
|
|
473
|
+
outcomeType: 'blocked',
|
|
474
|
+
message: 'Protected fill failed during protected execution, so this claimed request must not be reused.',
|
|
475
|
+
fillRef,
|
|
476
|
+
requestId,
|
|
477
|
+
...serializeSecretRequestContext(getSecretRequestSnapshot(session, requestId)),
|
|
478
|
+
requestStatus: latestRequest.status,
|
|
479
|
+
requestReusable: false,
|
|
480
|
+
nextAction: 'ask-user',
|
|
481
|
+
reason: execution.reason,
|
|
482
|
+
}),
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
catch (error) {
|
|
487
|
+
activateProtectedExposure(session, fillableForm, requestId, 'protected_fill_unexpected_error');
|
|
310
488
|
finalResult = {
|
|
311
489
|
success: false,
|
|
312
|
-
payload: {
|
|
490
|
+
payload: withFillableFormPresence(fillableForm, {
|
|
313
491
|
error: 'protected_fill_execution_failed',
|
|
314
492
|
outcomeType: 'blocked',
|
|
315
|
-
message: 'Protected fill failed during protected execution, so this
|
|
493
|
+
message: 'Protected fill failed during protected execution, so this claimed request must not be reused.',
|
|
316
494
|
fillRef,
|
|
317
|
-
|
|
318
|
-
...
|
|
319
|
-
|
|
495
|
+
requestId,
|
|
496
|
+
...serializeSecretRequestContext(getSecretRequestSnapshot(session, requestId)),
|
|
497
|
+
requestStatus: latestRequest.status,
|
|
498
|
+
requestReusable: false,
|
|
320
499
|
nextAction: 'ask-user',
|
|
321
|
-
reason:
|
|
322
|
-
},
|
|
500
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
501
|
+
}),
|
|
323
502
|
};
|
|
324
503
|
}
|
|
325
504
|
}
|
|
326
|
-
catch (error) {
|
|
327
|
-
const completedIntent = completeIntent(session, intentId);
|
|
328
|
-
activateProtectedExposure(session, fillableForm, intentId, 'protected_fill_unexpected_error');
|
|
329
|
-
finalResult = {
|
|
330
|
-
success: false,
|
|
331
|
-
payload: {
|
|
332
|
-
error: 'protected_fill_execution_failed',
|
|
333
|
-
outcomeType: 'blocked',
|
|
334
|
-
message: 'Protected fill failed during protected execution, so this approved intent must not be reused.',
|
|
335
|
-
fillRef,
|
|
336
|
-
intentId,
|
|
337
|
-
...serializeSecretIntentContext(completedIntent),
|
|
338
|
-
intentStatus: completedIntent.status,
|
|
339
|
-
nextAction: 'ask-user',
|
|
340
|
-
reason: error instanceof Error ? error.message : String(error),
|
|
341
|
-
},
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
505
|
}
|
|
345
506
|
}
|
|
507
|
+
catch (error) {
|
|
508
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, withFillableFormPresence(fillableForm, {
|
|
509
|
+
error: 'browser_connection_failed',
|
|
510
|
+
message: 'Protected fill could not connect to the browser.',
|
|
511
|
+
fillRef,
|
|
512
|
+
requestId,
|
|
513
|
+
...serializeSecretRequestContext(latestRequest),
|
|
514
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
515
|
+
}), {
|
|
516
|
+
pageRef: fillableForm.pageRef,
|
|
517
|
+
fillRef,
|
|
518
|
+
requestId,
|
|
519
|
+
});
|
|
520
|
+
}
|
|
346
521
|
finally {
|
|
347
|
-
deleteCachedTransientSecret(session, intentId);
|
|
348
|
-
saveSession(session);
|
|
349
522
|
if (browser) {
|
|
350
|
-
disconnectPlaywright(browser);
|
|
523
|
+
await disconnectPlaywright(browser);
|
|
351
524
|
}
|
|
352
525
|
}
|
|
353
526
|
if (!finalResult) {
|
|
354
|
-
return
|
|
527
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, withFillableFormPresence(fillableForm, {
|
|
355
528
|
error: 'protected_fill_execution_failed',
|
|
356
529
|
outcomeType: 'blocked',
|
|
357
530
|
message: 'Protected fill did not produce a final result.',
|
|
358
531
|
reason: 'Protected execution finished without returning a terminal success or failure payload.',
|
|
359
532
|
fillRef,
|
|
360
|
-
|
|
361
|
-
...
|
|
533
|
+
requestId,
|
|
534
|
+
...serializeSecretRequestContext(latestRequest),
|
|
535
|
+
}), {
|
|
536
|
+
pageRef: fillableForm.pageRef,
|
|
537
|
+
fillRef,
|
|
538
|
+
requestId,
|
|
362
539
|
});
|
|
363
540
|
}
|
|
364
541
|
if (!finalResult.success) {
|
|
365
|
-
return
|
|
542
|
+
return emitFillSecretFailure(session, session.activeRunId, fillSecretStep?.stepId, finalResult.payload, {
|
|
543
|
+
pageRef: fillableForm.pageRef,
|
|
544
|
+
fillRef,
|
|
545
|
+
requestId,
|
|
546
|
+
});
|
|
366
547
|
}
|
|
367
|
-
return
|
|
548
|
+
return emitFillSecretSuccess(session, session.activeRunId, fillSecretStep?.stepId, {
|
|
368
549
|
success: true,
|
|
369
550
|
...finalResult.payload,
|
|
551
|
+
}, {
|
|
552
|
+
pageRef: fillableForm.pageRef,
|
|
553
|
+
fillRef,
|
|
554
|
+
requestId,
|
|
370
555
|
});
|
|
371
556
|
}
|