@reclaimprotocol/agent 0.1.23 → 0.1.25
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 +56 -20
- package/lib/authoring/backend.d.ts +5 -4
- package/lib/authoring/tools.js +30 -30
- package/lib/cdp/capture-engine.js +8 -7
- package/lib/cdp/claims.d.ts +21 -0
- package/lib/cdp/claims.js +129 -0
- package/lib/cdp/container.d.ts +85 -0
- package/lib/cdp/container.js +481 -0
- package/lib/cdp/geo.d.ts +10 -0
- package/lib/cdp/geo.js +36 -0
- package/lib/cdp/index.d.ts +1 -0
- package/lib/cdp/index.js +1 -0
- package/lib/live/cloudflared.d.ts +15 -0
- package/lib/live/cloudflared.js +268 -0
- package/lib/live/tunnel.d.ts +26 -0
- package/lib/live/tunnel.js +160 -0
- package/lib/mcp/api/operations.gen.js +34 -26
- package/lib/mcp/api/to-zod.d.ts +1 -1
- package/lib/mcp/api/to-zod.js +1 -1
- package/lib/mcp/api/tools.js +1 -1
- package/lib/mcp/instructions.d.ts +15 -2
- package/lib/mcp/instructions.js +102 -38
- package/lib/mcp/start.js +62 -6
- package/lib/mcp/tools/agent/analyze.js +5 -1
- package/lib/mcp/tools/agent/attach.d.ts +29 -2
- package/lib/mcp/tools/agent/attach.js +310 -24
- package/lib/mcp/tools/agent/build.d.ts +18 -8
- package/lib/mcp/tools/agent/build.js +30 -12
- package/lib/mcp/tools/agent/capture.js +5 -1
- package/lib/mcp/tools/agent/eval.js +3 -1
- package/lib/mcp/tools/agent/find.js +6 -5
- package/lib/mcp/tools/agent/how-it-works.d.ts +15 -7
- package/lib/mcp/tools/agent/how-it-works.js +57 -17
- package/lib/mcp/tools/agent/index.d.ts +1 -2
- package/lib/mcp/tools/agent/index.js +1 -1
- package/lib/mcp/tools/agent/live-view.d.ts +17 -0
- package/lib/mcp/tools/agent/live-view.js +146 -0
- package/lib/mcp/tools/agent/pod-proof.d.ts +8 -0
- package/lib/mcp/tools/agent/pod-proof.js +64 -0
- package/lib/mcp/tools/agent/propose.js +4 -2
- package/lib/mcp/tools/agent/publish.js +47 -77
- package/lib/mcp/tools/agent/session.d.ts +16 -1
- package/lib/mcp/tools/agent/session.js +32 -7
- package/lib/mcp/tools/authenticate/authenticate.js +26 -13
- package/lib/mcp/tools/mode/mode.d.ts +1 -1
- package/lib/mcp/tools/mode/mode.js +10 -22
- package/lib/old/client.d.ts +1 -1
- package/lib/old/client.js +1 -1
- package/lib/old/instructions.d.ts +9 -1
- package/lib/old/instructions.js +4 -6
- package/lib/old/login-cdp.d.ts +2 -2
- package/lib/old/login-cdp.js +46 -6
- package/lib/old/to-register.d.ts +3 -2
- package/lib/old/to-register.js +1 -1
- package/lib/old/tools/authenticate.js +9 -1
- package/lib/old/tools/get-provider-info.js +6 -5
- package/lib/old/tools/issue-app-credentials.js +3 -2
- package/lib/old/tools/publish.d.ts +1 -1
- package/lib/old/tools/publish.js +90 -131
- package/lib/old/tools/update-provider-metadata.d.ts +1 -1
- package/lib/old/tools/update-provider-metadata.js +1 -1
- package/lib/old/tools/verify-sdk-setup.js +1 -1
- package/lib/proof/attestor.d.ts +3 -3
- package/lib/proof/debug-response-dump.js +4 -4
- package/lib/proof/index.d.ts +1 -0
- package/lib/proof/index.js +1 -0
- package/lib/proof/page-replay.d.ts +1 -1
- package/lib/proof/page-replay.js +1 -1
- package/lib/proof/pod-prover.d.ts +47 -0
- package/lib/proof/pod-prover.js +155 -0
- package/lib/provider/dom-xpath.js +11 -9
- package/lib/provider/draft.d.ts +10 -7
- package/lib/provider/draft.js +11 -9
- package/lib/provider/injection-doc.d.ts +23 -1
- package/lib/provider/injection-doc.js +34 -21
- package/lib/provider/match-redaction-warning.d.ts +2 -2
- package/lib/provider/match-redaction-warning.js +3 -3
- package/lib/provider/matcher.js +13 -12
- package/lib/provider/secrets.d.ts +3 -3
- package/lib/provider/secrets.js +3 -3
- package/lib/provider/to-version.d.ts +7 -6
- package/lib/provider/to-version.js +3 -3
- package/lib/tools/registry.d.ts +5 -5
- package/lib/tools/registry.js +5 -5
- package/package.json +3 -3
- package/samples/demo-server/README.md +7 -6
- package/skill/SKILL.builder.md +356 -189
- package/skill/SKILL.common.md +400 -97
- package/skill/SKILL.old.md +340 -155
- package/skill/builder-mode.md +60 -17
- package/skill/hash-validation.md +170 -0
- package/skill/interception.md +236 -0
- package/skill/js-sdk-integration.md +13 -7
- package/skill/old-mode.md +62 -21
- package/skill/user-script.md +61 -0
- package/src/authoring/backend.ts +5 -4
- package/src/authoring/tools.ts +31 -30
- package/src/cdp/capture-engine.ts +8 -7
- package/src/cdp/claims.ts +153 -0
- package/src/cdp/container.ts +593 -0
- package/src/cdp/geo.ts +52 -0
- package/src/cdp/index.ts +1 -0
- package/src/consts.ts +1 -0
- package/src/live/cloudflared.ts +348 -0
- package/src/live/tunnel.ts +208 -0
- package/src/mcp/api/operations.gen.ts +34 -26
- package/src/mcp/api/to-zod.ts +1 -1
- package/src/mcp/api/tools.ts +1 -1
- package/src/mcp/instructions.ts +122 -48
- package/src/mcp/start.ts +69 -5
- package/src/mcp/tools/agent/analyze.ts +5 -1
- package/src/mcp/tools/agent/attach.ts +367 -26
- package/src/mcp/tools/agent/build.ts +35 -16
- package/src/mcp/tools/agent/capture.ts +5 -1
- package/src/mcp/tools/agent/eval.ts +4 -1
- package/src/mcp/tools/agent/find.ts +6 -5
- package/src/mcp/tools/agent/how-it-works.ts +62 -21
- package/src/mcp/tools/agent/index.ts +6 -2
- package/src/mcp/tools/agent/live-view.ts +182 -0
- package/src/mcp/tools/agent/pod-proof.ts +90 -0
- package/src/mcp/tools/agent/propose.ts +4 -2
- package/src/mcp/tools/agent/publish.ts +52 -77
- package/src/mcp/tools/agent/session.ts +33 -6
- package/src/mcp/tools/authenticate/authenticate.ts +28 -13
- package/src/mcp/tools/mode/mode.ts +10 -22
- package/src/old/client.ts +2 -2
- package/src/old/instructions.ts +4 -10
- package/src/old/login-cdp.ts +50 -6
- package/src/old/to-register.ts +3 -2
- package/src/old/tools/authenticate.ts +9 -1
- package/src/old/tools/get-provider-info.ts +6 -5
- package/src/old/tools/issue-app-credentials.ts +3 -2
- package/src/old/tools/publish.ts +95 -131
- package/src/old/tools/update-provider-metadata.ts +1 -1
- package/src/old/tools/verify-sdk-setup.ts +1 -1
- package/src/proof/attestor.ts +3 -3
- package/src/proof/debug-response-dump.ts +4 -4
- package/src/proof/index.ts +8 -0
- package/src/proof/page-replay.ts +1 -1
- package/src/proof/pod-prover.ts +231 -0
- package/src/provider/dom-xpath.ts +11 -9
- package/src/provider/draft.ts +13 -10
- package/src/provider/injection-doc.ts +37 -24
- package/src/provider/match-redaction-warning.ts +3 -3
- package/src/provider/matcher.ts +13 -12
- package/src/provider/secrets.ts +3 -3
- package/src/provider/to-version.ts +11 -9
- package/src/tools/registry.ts +5 -5
- package/skill/injection-api.md +0 -364
package/lib/old/tools/publish.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Boom, isBoom } from '@hapi/boom';
|
|
2
2
|
import { defineTool } from "../../mcp/server.js";
|
|
3
|
-
import {
|
|
3
|
+
import { ALLOWED_REQUESTS_HINT, USER_SCRIPT_HINT, } from "../../provider/injection-doc.js";
|
|
4
4
|
import { countsFor, matchRedactionWarnings, } from "../../provider/match-redaction-warning.js";
|
|
5
5
|
import { bumpPatchString, extractVersions, injectedRequestDataFrom, providerToConfigBody, providerToRegisterBody, } from "../to-register.js";
|
|
6
6
|
const DEFAULT_VERSION_INFO = 'Updated from MCP browser capture';
|
|
@@ -15,8 +15,8 @@ function extractProviderId(resp) {
|
|
|
15
15
|
* `providerId` for a public provider (or anyone else's) comes back as
|
|
16
16
|
* 401/403/404 — the dev's likely intent is to publish their OWN version of that
|
|
17
17
|
* site, which on this backend means registering a separate copy. Rethrow those
|
|
18
|
-
* failures with that actionable suggestion; leave other errors (
|
|
19
|
-
* version collision) untouched so their real detail surfaces.
|
|
18
|
+
* failures with that actionable suggestion; leave other errors (for example, a
|
|
19
|
+
* 400 version collision) untouched so their real detail surfaces.
|
|
20
20
|
*/
|
|
21
21
|
function rethrowOwnershipError(err, providerId) {
|
|
22
22
|
const status = isBoom(err) ? err.output.statusCode : undefined;
|
|
@@ -37,7 +37,7 @@ function rethrowOwnershipError(err, providerId) {
|
|
|
37
37
|
/**
|
|
38
38
|
* Publish a drafted provider to the OLD devtools backend. Keeps the builder
|
|
39
39
|
* tool NAME (`create_provider_version_from_capture`) so the skill flow is
|
|
40
|
-
* unchanged, but the
|
|
40
|
+
* unchanged, but the behavior differs:
|
|
41
41
|
*
|
|
42
42
|
* - WITHOUT `providerId` → `POST /api/providers/register`: creates a
|
|
43
43
|
* brand-new provider + version 1.0.0. Re-running creates a DUPLICATE.
|
|
@@ -56,63 +56,38 @@ function rethrowOwnershipError(err, providerId) {
|
|
|
56
56
|
export function createVersionFromCaptureTool(client, attachRef) {
|
|
57
57
|
return defineTool({
|
|
58
58
|
name: 'create_provider_version_from_capture',
|
|
59
|
-
description: 'Publish drafted ReclaimProvider(s) to the devtools backend. '
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
'
|
|
64
|
-
'`
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'`
|
|
69
|
-
'
|
|
70
|
-
'(
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
|
|
78
|
-
'
|
|
79
|
-
'
|
|
80
|
-
|
|
81
|
-
'
|
|
82
|
-
'
|
|
83
|
-
'
|
|
84
|
-
'
|
|
85
|
-
'
|
|
86
|
-
'
|
|
87
|
-
'
|
|
88
|
-
'
|
|
89
|
-
'
|
|
90
|
-
'
|
|
91
|
-
'`provider`/`providers`). Anything you OMIT is published blank/' +
|
|
92
|
-
'default in the new version, NOT preserved. To change one field ' +
|
|
93
|
-
'while keeping the rest, first read the current version with ' +
|
|
94
|
-
'get_provider_info, then pass the full desired config (the existing ' +
|
|
95
|
-
'values plus your change) back into this call. ' +
|
|
96
|
-
'`allowedInjectedRequestData`/`useIncognitoWebview`/' +
|
|
97
|
-
'`extensionConfig` only take effect on add-version — the register ' +
|
|
98
|
-
'endpoint (no `providerId`) ignores them, so on a fresh register ' +
|
|
99
|
-
'this tool automatically follows up with an add-version call that ' +
|
|
100
|
-
'applies them (also where document replay gets force-disabled — ' +
|
|
101
|
-
'see below). Per-request fields you may set on ' +
|
|
102
|
-
'`provider`/`providers`: `credentials` (omit/same-origin/include, ' +
|
|
103
|
-
'default include), `urlType` (REGEX/CONSTANT/TEMPLATE, default ' +
|
|
104
|
-
'derived from {{placeholders}}), and `isOptional` on each ' +
|
|
105
|
-
'responseMatch (default false). \n\n' +
|
|
106
|
-
'Captured requests must be GET/POST. OPRF redactions are supported. ' +
|
|
107
|
-
'Document replay — the HAWKEYE-level flag controlling whether the ' +
|
|
108
|
-
'page\'s own document/navigation request gets genuinely re-sent ' +
|
|
109
|
-
'through the interceptor at verification time — is ALWAYS ' +
|
|
110
|
-
'published disabled (`disableRequestReplay: true`); there is no ' +
|
|
111
|
-
'way to enable it here. ' +
|
|
112
|
-
'On success, if a browser is still attached, the response\'s ' +
|
|
113
|
-
'`_notes` reminds you to confirm with the developer before ' +
|
|
114
|
-
'calling `dispose_browser` — never close it unprompted, they ' +
|
|
115
|
-
'may want it for further edits.',
|
|
59
|
+
description: 'Publish drafted ReclaimProvider(s) to the devtools backend. Needs '
|
|
60
|
+
+ 'its OWN reclaim_authenticate login — authenticate_builder does NOT '
|
|
61
|
+
+ 'authorize this call. Pass the `provider` object(s) from '
|
|
62
|
+
+ 'propose_provider VERBATIM, plus the `initialUrl` the user landed '
|
|
63
|
+
+ 'on (the login/landing page, NOT the API url). Exactly one of '
|
|
64
|
+
+ '`provider` (one request) or `providers` (a multi-request '
|
|
65
|
+
+ 'provider — every entry becomes a parallel requestData entry, all '
|
|
66
|
+
+ 'verified together). Captured requests must be GET/POST; OPRF '
|
|
67
|
+
+ 'redactions are supported.\n\n'
|
|
68
|
+
+ 'Omit `providerId` to REGISTER A NEW provider (creates it + '
|
|
69
|
+
+ 'version 1.0.0 — re-running creates a DUPLICATE). Pass '
|
|
70
|
+
+ '`providerId` (from get_me_providers) to add a NEW VERSION to it; '
|
|
71
|
+
+ 'the patch auto-bumps. You can only version a provider YOU own — '
|
|
72
|
+
+ 'to publish your own take on one you don\'t own, omit '
|
|
73
|
+
+ '`providerId` to register your own copy.\n\n'
|
|
74
|
+
+ 'THIS BACKEND ONLY EVER CREATES A NEW VERSION — there is no '
|
|
75
|
+
+ 'partial-patch endpoint, and this tool carries NOTHING forward '
|
|
76
|
+
+ 'from the previous version: every version replaces the WHOLE '
|
|
77
|
+
+ 'providerConfig with exactly what you pass in THIS call. Any '
|
|
78
|
+
+ 'field you want to survive must be re-supplied here '
|
|
79
|
+
+ '(`customInjection`, `userAgent`, `pageTitle`, '
|
|
80
|
+
+ '`allowedInjectedRequestData`, `stepsToFollow`, '
|
|
81
|
+
+ '`useIncognitoWebview`, `extensionConfig`, `requestData`); '
|
|
82
|
+
+ 'anything omitted is published blank. To change one field, read '
|
|
83
|
+
+ 'the current config with get_provider_info first and pass it back '
|
|
84
|
+
+ 'with your edit. `allowedInjectedRequestData`/'
|
|
85
|
+
+ '`useIncognitoWebview`/`extensionConfig` apply on add-version '
|
|
86
|
+
+ 'only, so a fresh register auto-follows with an add-version call '
|
|
87
|
+
+ 'that applies them (and disables document replay — see '
|
|
88
|
+
+ '`disableRequestReplay`).\n\n'
|
|
89
|
+
+ 'Always read the response\'s `_notes`. '
|
|
90
|
+
+ 'Full walkthrough: how_it_works({ topic: "publish" }).',
|
|
116
91
|
inputSchema: {
|
|
117
92
|
type: 'object',
|
|
118
93
|
properties: {
|
|
@@ -214,15 +189,11 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
214
189
|
},
|
|
215
190
|
customInjection: {
|
|
216
191
|
type: 'string',
|
|
217
|
-
description:
|
|
218
|
-
'
|
|
219
|
-
'
|
|
220
|
-
'(window.
|
|
221
|
-
'
|
|
222
|
-
'only for rare edge cases, not navigation. The backend rejects ' +
|
|
223
|
-
'a few deprecated injection APIs (e.g. window.payloadData, ' +
|
|
224
|
-
'window.ReclaimInjected) with a 400. Guide:\n\n' +
|
|
225
|
-
INJECTION_GUIDE,
|
|
192
|
+
description: USER_SCRIPT_HINT
|
|
193
|
+
+ ' Old-devtools\' name for what the builder calls '
|
|
194
|
+
+ 'webSettings.jsUserScripts. The backend rejects a few '
|
|
195
|
+
+ 'deprecated injection APIs (window.payloadData, '
|
|
196
|
+
+ 'window.ReclaimInjected) with a 400.',
|
|
226
197
|
},
|
|
227
198
|
userAgent: {
|
|
228
199
|
type: 'object',
|
|
@@ -239,39 +210,15 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
239
210
|
},
|
|
240
211
|
allowedInjectedRequestData: {
|
|
241
212
|
type: 'array',
|
|
242
|
-
description: 'Extra requests the customInjection script is allowed to '
|
|
243
|
-
'fire (
|
|
244
|
-
'
|
|
245
|
-
'
|
|
246
|
-
|
|
247
|
-
'
|
|
248
|
-
'
|
|
249
|
-
'
|
|
250
|
-
|
|
251
|
-
'the "bodySniff" section of the customInjection field\'s guide ' +
|
|
252
|
-
'for the exact mechanics and a worked example. ' +
|
|
253
|
-
'⚠️ BEFORE populating this to gate ' +
|
|
254
|
-
'`verifyProof(proof, { providerId })`: this whole entry (url, ' +
|
|
255
|
-
'method, body, responseMatches, responseRedactions) feeds a ' +
|
|
256
|
-
'client-side hash-equality check, and `url` is hashed VERBATIM ' +
|
|
257
|
-
'— no regex/template resolution, even with `urlType: REGEX` or ' +
|
|
258
|
-
'`TEMPLATE`. If the real captured URL contains ANY per-session ' +
|
|
259
|
-
'part (a tracking nonce, CSRF token, cache-busting timestamp), ' +
|
|
260
|
-
'no declared spec can EVER hash-match a real proof, no matter ' +
|
|
261
|
-
'how correct the rest of this entry is — populating' +
|
|
262
|
-
'it for such ' +
|
|
263
|
-
'a provider makes verifyProof reject every real proof,' +
|
|
264
|
-
'which is ' +
|
|
265
|
-
'worse than leaving this field empty. Diff the same endpoint\'s' +
|
|
266
|
-
' captured URL across two separate sessions before wiring this ' +
|
|
267
|
-
'up. If provider-hash validation keeps causing problems ' +
|
|
268
|
-
'(unstable url, or any other persistent mismatch), the ' +
|
|
269
|
-
'fallback on the verifying side is `verifyProof(proof, { ' +
|
|
270
|
-
'dangerouslyDisableContentValidation: true })` — trusts only ' +
|
|
271
|
-
'the attestor\'s signature, skips the hash-equality check ' +
|
|
272
|
-
'entirely; see the "Provider-hash validation" section of the ' +
|
|
273
|
-
'customInjection field\'s guide for the full mechanics and ' +
|
|
274
|
-
'when to reach for it.',
|
|
213
|
+
description: 'Extra requests the customInjection user script is allowed to '
|
|
214
|
+
+ 'fire (for example, pagination) — add-version ONLY, the '
|
|
215
|
+
+ 'register '
|
|
216
|
+
+ 'endpoint ignores it. Each item has the same shape as '
|
|
217
|
+
+ '`provider`, plus `multiple`/`required` (default true). Set '
|
|
218
|
+
+ '`body` whenever the request has one (see its own description '
|
|
219
|
+
+ 'below). The builder calls the same concept '
|
|
220
|
+
+ '`allowedJsRequests`. '
|
|
221
|
+
+ ALLOWED_REQUESTS_HINT,
|
|
275
222
|
items: {
|
|
276
223
|
type: 'object',
|
|
277
224
|
properties: {
|
|
@@ -291,7 +238,8 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
291
238
|
'body at all (skip only for a genuinely bodyless ' +
|
|
292
239
|
'request, typically GET). If the real body is FIXED ' +
|
|
293
240
|
'(identical for every user/run), put that literal body ' +
|
|
294
|
-
'text here verbatim. If only PART of it varies (
|
|
241
|
+
'text here verbatim. If only PART of it varies (for ' +
|
|
242
|
+
'example, ' +
|
|
295
243
|
'`{"request":1,"type":"user_info","id":"12345"}` where ' +
|
|
296
244
|
'only `id` differs per user), template ONLY that part: ' +
|
|
297
245
|
'`{"request":1,"type":"user_info",' +
|
|
@@ -314,7 +262,7 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
314
262
|
'reproduces the real captured request body ' +
|
|
315
263
|
'byte-for-byte. Fallback if per-field templating keeps ' +
|
|
316
264
|
'mismatching (more fields vary than expected, unstable ' +
|
|
317
|
-
'key order,
|
|
265
|
+
'key order, and so on) and you can\'t pin down every ' +
|
|
318
266
|
'variable field: template the WHOLE body as one ' +
|
|
319
267
|
'placeholder instead, `{{REQ_BODY_GRD}}` — the `GRD` ' +
|
|
320
268
|
'suffix makes it a greedy match (captures everything) ' +
|
|
@@ -331,7 +279,7 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
331
279
|
'`value` must literally appear (or match, if `regex`) ' +
|
|
332
280
|
'somewhere in the response body for the claim to be ' +
|
|
333
281
|
'accepted; it commonly embeds one or more ' +
|
|
334
|
-
'`{{paramName}}` extraction placeholders (
|
|
282
|
+
'`{{paramName}}` extraction placeholders (for example, ' +
|
|
335
283
|
'`"name":"{{name_0}}"`) whose real value is redacted ' +
|
|
336
284
|
'out and supplied separately as a witness/extracted ' +
|
|
337
285
|
'param. Use `${var}` (not `{{var}}`) inside this string ' +
|
|
@@ -346,7 +294,8 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
346
294
|
description: 'Each item: `{ jsonPath?: string, xPath?: string, ' +
|
|
347
295
|
'regex?: string, hash?: string }`. Identifies WHICH ' +
|
|
348
296
|
'part of the response the matching `{{paramName}}` in ' +
|
|
349
|
-
'`responseMatches` actually redacts
|
|
297
|
+
'`responseMatches` actually redacts or extracts — for ' +
|
|
298
|
+
'example, ' +
|
|
350
299
|
'`jsonPath: "$.data.items[0].name"` for a JSON response. ' +
|
|
351
300
|
'Order/count should line up with `responseMatches`\' ' +
|
|
352
301
|
'placeholders one-to-one for a typical claim.',
|
|
@@ -404,17 +353,27 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
404
353
|
'unset — the devtools backend\'s own column default ' +
|
|
405
354
|
'(`HAWKEYE`) applies, which is inert and harmless for the ' +
|
|
406
355
|
'standard capture→replay flow with no interceptor script ' +
|
|
407
|
-
'installed. Only set
|
|
408
|
-
'
|
|
409
|
-
'that calls ' +
|
|
356
|
+
'installed. Only set `HAWKEYE`/`MSWJS`/`XHOOK` when you are ' +
|
|
357
|
+
'ALSO supplying a `customInjection` script that calls ' +
|
|
410
358
|
'`window.reclaimInterceptor.addResponseMiddleware(...)` for ' +
|
|
411
|
-
'genuine live interception, or set `NONE` explicitly
|
|
412
|
-
'
|
|
413
|
-
'
|
|
414
|
-
'
|
|
415
|
-
'
|
|
416
|
-
'
|
|
417
|
-
|
|
359
|
+
'genuine live interception, or set `NONE` explicitly to be ' +
|
|
360
|
+
'certain none is configured. Builder calls the equivalent ' +
|
|
361
|
+
'concept `interceptorType` (no `NONE` there — omitting the ' +
|
|
362
|
+
'whole `interceptorOptions` object is its no-interception ' +
|
|
363
|
+
'signal instead). What each value actually does: ' +
|
|
364
|
+
'how_it_works({ topic: "interception" }).',
|
|
365
|
+
},
|
|
366
|
+
disableRequestReplay: {
|
|
367
|
+
type: 'boolean',
|
|
368
|
+
description: 'Whether the page\'s own document/navigation request is ' +
|
|
369
|
+
'skipped (constructed locally) instead of genuinely replayed ' +
|
|
370
|
+
'through the interceptor. Defaults to `true` (disabled) when ' +
|
|
371
|
+
'omitted. Only meaningful for `injectionType` ' +
|
|
372
|
+
'HAWKEYE/MSWJS/XHOOK — pass `false` to enable real document ' +
|
|
373
|
+
'replay for those (for example, the target value is embedded ' +
|
|
374
|
+
'in the page\'s own HTML). Inert when `injectionType` is ' +
|
|
375
|
+
'`CDP` or ' +
|
|
376
|
+
'unset.',
|
|
418
377
|
},
|
|
419
378
|
},
|
|
420
379
|
required: ['initialUrl'],
|
|
@@ -453,9 +412,9 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
453
412
|
// column default applies when omitted, same as before this field
|
|
454
413
|
// existed at all.
|
|
455
414
|
injectionType: args.injectionType,
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
disableRequestReplay: true,
|
|
415
|
+
// Author-settable; defaults to disabled (see tool description).
|
|
416
|
+
// Only meaningful for HAWKEYE/MSWJS/XHOOK — inert for CDP.
|
|
417
|
+
disableRequestReplay: args.disableRequestReplay ?? true,
|
|
459
418
|
allowedInjectedRequestData: args.allowedInjectedRequestData
|
|
460
419
|
? injectedRequestDataFrom(args.allowedInjectedRequestData)
|
|
461
420
|
: undefined
|
|
@@ -494,12 +453,12 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
494
453
|
'every page load (before navigating to initialUrl), matching ' +
|
|
495
454
|
'the builder\'s jsUserScripts.');
|
|
496
455
|
}
|
|
497
|
-
// disableRequestReplay is honored ONLY on add-version
|
|
498
|
-
//
|
|
499
|
-
//
|
|
500
|
-
// an explicit injectionType, when passed —
|
|
501
|
-
// register persists it — and any other
|
|
502
|
-
// caller passed).
|
|
456
|
+
// disableRequestReplay is honored ONLY on add-version — so every
|
|
457
|
+
// register is immediately followed by an add-version call that
|
|
458
|
+
// actually applies it (whatever value — default or author-set;
|
|
459
|
+
// which also lands an explicit injectionType, when passed —
|
|
460
|
+
// unverified whether register persists it — and any other
|
|
461
|
+
// register-ignored fields the caller passed).
|
|
503
462
|
const REGISTER_IGNORED_KEYS = [
|
|
504
463
|
'allowedInjectedRequestData',
|
|
505
464
|
'useIncognitoWebview',
|
|
@@ -512,8 +471,8 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
512
471
|
`${ignoredOnRegister.length > 1 ? 'are' : 'is'} ` +
|
|
513
472
|
'ignored on register (no providerId) — the devtools backend only ' +
|
|
514
473
|
'reads them when adding a version. They were applied by the ' +
|
|
515
|
-
'automatic follow-up version this tool always creates to ' +
|
|
516
|
-
'
|
|
474
|
+
'automatic follow-up version this tool always creates to apply ' +
|
|
475
|
+
'disableRequestReplay.');
|
|
517
476
|
}
|
|
518
477
|
const body = providerToRegisterBody(providers, opts);
|
|
519
478
|
const registered = await client.registerProvider(body);
|
|
@@ -531,7 +490,7 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
531
490
|
const configBody = providerToConfigBody(providers, opts, followVersion, DEFAULT_VERSION_INFO);
|
|
532
491
|
await client.updateProviderConfig(newProviderId, configBody);
|
|
533
492
|
notes.push(`Created an automatic follow-up version (${followVersion}) to ` +
|
|
534
|
-
|
|
493
|
+
`apply disableRequestReplay (${opts.disableRequestReplay})` +
|
|
535
494
|
(opts.injectionType !== undefined
|
|
536
495
|
? ` and set injectionType (${opts.injectionType})`
|
|
537
496
|
: '') +
|
|
@@ -551,7 +510,7 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
551
510
|
}
|
|
552
511
|
}
|
|
553
512
|
else {
|
|
554
|
-
notes.push('Could not
|
|
513
|
+
notes.push('Could not apply disableRequestReplay: the ' +
|
|
555
514
|
'register response did not include the new providerId. Call ' +
|
|
556
515
|
'this tool again WITH `providerId` to create a version that ' +
|
|
557
516
|
'applies them.');
|
|
@@ -559,7 +518,7 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
559
518
|
return withNotes(registered);
|
|
560
519
|
}
|
|
561
520
|
// New version of an existing provider — pick the next patch above
|
|
562
|
-
// the highest existing version. A provider you don't own (
|
|
521
|
+
// the highest existing version. A provider you don't own (for example, a
|
|
563
522
|
// public one) fails here with 401/403/404; surface the register-a-copy
|
|
564
523
|
// workaround instead of a bare permission error.
|
|
565
524
|
const providerId = args.providerId;
|
|
@@ -7,7 +7,7 @@ import type { ReclaimOldClient } from '../client.ts';
|
|
|
7
7
|
* `create_provider_version_from_capture` paths: it does NOT touch
|
|
8
8
|
* `providerConfig`/versions at all, and only the fields you pass here
|
|
9
9
|
* change — everything else on the provider is left untouched (no need to
|
|
10
|
-
* re-supply `requestData`/`customInjection
|
|
10
|
+
* re-supply `requestData`/`customInjection`, and so on, and
|
|
11
11
|
* no new version is created).
|
|
12
12
|
*
|
|
13
13
|
* The backend 403s if you don't own the provider (and aren't an admin) —
|
|
@@ -6,7 +6,7 @@ import { defineTool } from "../../mcp/server.js";
|
|
|
6
6
|
* `create_provider_version_from_capture` paths: it does NOT touch
|
|
7
7
|
* `providerConfig`/versions at all, and only the fields you pass here
|
|
8
8
|
* change — everything else on the provider is left untouched (no need to
|
|
9
|
-
* re-supply `requestData`/`customInjection
|
|
9
|
+
* re-supply `requestData`/`customInjection`, and so on, and
|
|
10
10
|
* no new version is created).
|
|
11
11
|
*
|
|
12
12
|
* The backend 403s if you don't own the provider (and aren't an admin) —
|
|
@@ -101,7 +101,7 @@ export function verifySdkSetupTool(client) {
|
|
|
101
101
|
: 'PUBLIC_URL not set — fine if you only read the proof from the ' +
|
|
102
102
|
'frontend flow, but the async webhook callback needs a ' +
|
|
103
103
|
'publicly-reachable URL or it will never fire. Get one via a ' +
|
|
104
|
-
'tunnel (
|
|
104
|
+
'tunnel (for example, `ngrok http <port>`) or by deploying to a ' +
|
|
105
105
|
'dev/staging server you already have — ask the user which they ' +
|
|
106
106
|
'prefer.',
|
|
107
107
|
});
|
package/lib/proof/attestor.d.ts
CHANGED
|
@@ -24,13 +24,13 @@ export interface RunAttestorProofOptions {
|
|
|
24
24
|
/** When resolving the key from env/.env/file, the address the caller expects
|
|
25
25
|
* to sign with (sanity check). Ignored when `ownerPrivateKey` is given. */
|
|
26
26
|
ownerAddress?: string;
|
|
27
|
-
/** Sign with this key directly (
|
|
28
|
-
* instead of resolving from env/.env/file. */
|
|
27
|
+
/** Sign with this key directly (for example, the app or VC's ephemeral
|
|
28
|
+
* per-session key) instead of resolving from env/.env/file. */
|
|
29
29
|
ownerPrivateKey?: string;
|
|
30
30
|
/** ZK engine for `createClaimOnAttestor`. Defaults to `'stwo'` — a pure-WASM
|
|
31
31
|
* prover that runs everywhere (no native shared library, so it works on
|
|
32
32
|
* Windows where `'gnark'` fails to load its `.dll`). Server-side paths that
|
|
33
|
-
* want gnark's speed pin it explicitly (
|
|
33
|
+
* want gnark's speed pin it explicitly (for example, the verify runner). */
|
|
34
34
|
zkEngine?: 'gnark' | 'snarkjs' | 'stwo';
|
|
35
35
|
/** Extract the structured {@link AttestorClaim} (claim + attestor signature)
|
|
36
36
|
* onto the result for nested-proof construction. */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Debug helper (gated by RECLAIM_AGENT_DUMP_RESPONSE): capture the EXACT
|
|
2
2
|
// response bytes the attestor validates a claim against, plus a per-match
|
|
3
3
|
// presence check. A "Response does not contain X" failure means the attestor's
|
|
4
|
-
// server-side re-fetch differs from what the browser (replay) saw —
|
|
5
|
-
// embeds nav/userMenu data for browser requests but not for the
|
|
6
|
-
// fetch. Seeing the attestor's actual response is the only way
|
|
7
|
-
// really returned.
|
|
4
|
+
// server-side re-fetch differs from what the browser (replay) saw — for
|
|
5
|
+
// example, GitHub embeds nav/userMenu data for browser requests but not for the
|
|
6
|
+
// attestor's raw fetch. Seeing the attestor's actual response is the only way
|
|
7
|
+
// to tell what it really returned.
|
|
8
8
|
//
|
|
9
9
|
// On each getResponseRedactions call it writes the response to
|
|
10
10
|
// `attestor-last-response.html` in the process CWD and logs the byte count +,
|
package/lib/proof/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type { AttestorClaim, AttestorLogEntry, ProofResult, RunAttestorProofOptions, } from './attestor.ts';
|
|
2
2
|
export { runAttestorProof, tailLogs, warnsAndErrors } from './attestor.ts';
|
|
3
3
|
export { buildHttpParams, ensureAttestorCrypto, type ParsedClaim, parseClaim, resolveAttestorUrl, } from './proof-core.ts';
|
|
4
|
+
export { type HttpParams, type HttpSecretParams, type PopcornProveOptions, popcornProve, popcornValidateExtraction, type ValidateExtractionResult, } from './pod-prover.ts';
|
|
4
5
|
export { ensureZkFiles } from './zk-files.ts';
|
|
5
6
|
export { createClaimOnAttestor } from '@reclaimprotocol/attestor-core';
|
package/lib/proof/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { runAttestorProof, tailLogs, warnsAndErrors } from "./attestor.js";
|
|
2
2
|
export { buildHttpParams, ensureAttestorCrypto, parseClaim, resolveAttestorUrl, } from "./proof-core.js";
|
|
3
|
+
export { popcornProve, popcornValidateExtraction, } from "./pod-prover.js";
|
|
3
4
|
export { ensureZkFiles } from "./zk-files.js";
|
|
4
5
|
// Re-exported attestor-core claim primitive so the agent is the single
|
|
5
6
|
// integration point with @reclaimprotocol/attestor-core across the builder.
|
|
@@ -23,7 +23,7 @@ export interface PageReplayTarget {
|
|
|
23
23
|
* (`authenticatedPageFetch`) so cookies are the real browser's, which a
|
|
24
24
|
* detached call could never reproduce without manually re-deriving them.
|
|
25
25
|
* WITH `withoutSecrets` (the auth-bound check — "does this still work with
|
|
26
|
-
* no credentials,
|
|
26
|
+
* no credentials, that is, is it actually public"), replay instead through the
|
|
27
27
|
* detached Node-side `replayProvider`: the whole point of that check is to
|
|
28
28
|
* prove NO secret rides along, and the live page's own global `fetch` can't
|
|
29
29
|
* give that guarantee — a site (or a script installed via test_user_script)
|
package/lib/proof/page-replay.js
CHANGED
|
@@ -56,7 +56,7 @@ function authenticatedPageFetch(backend, provider, secrets) {
|
|
|
56
56
|
* (`authenticatedPageFetch`) so cookies are the real browser's, which a
|
|
57
57
|
* detached call could never reproduce without manually re-deriving them.
|
|
58
58
|
* WITH `withoutSecrets` (the auth-bound check — "does this still work with
|
|
59
|
-
* no credentials,
|
|
59
|
+
* no credentials, that is, is it actually public"), replay instead through the
|
|
60
60
|
* detached Node-side `replayProvider`: the whole point of that check is to
|
|
61
61
|
* prove NO secret rides along, and the live page's own global `fetch` can't
|
|
62
62
|
* give that guarantee — a site (or a script installed via test_user_script)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ProviderParams } from '@reclaimprotocol/attestor-core';
|
|
2
|
+
import type { ProofResult } from './attestor.ts';
|
|
3
|
+
/** Attestor HTTP provider params — the recipe the agent synthesis produces. */
|
|
4
|
+
export type HttpParams = ProviderParams<'http'>;
|
|
5
|
+
/** Captured secrets for the replay, exactly as `/reclaim/prove` wants them. */
|
|
6
|
+
export interface HttpSecretParams {
|
|
7
|
+
cookieStr?: string;
|
|
8
|
+
authorisationHeader?: string;
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
paramValues?: Record<string, string>;
|
|
11
|
+
}
|
|
12
|
+
export interface PopcornProveOptions {
|
|
13
|
+
/** Pod API base (the session's `apiUrl`). */
|
|
14
|
+
apiUrl: string;
|
|
15
|
+
params: HttpParams;
|
|
16
|
+
secretParams: HttpSecretParams;
|
|
17
|
+
/** Session context, stringified into the claim context if given. */
|
|
18
|
+
context?: Record<string, unknown>;
|
|
19
|
+
fetchImpl?: typeof fetch;
|
|
20
|
+
}
|
|
21
|
+
export interface ValidateExtractionResult {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
extractedValue?: string;
|
|
24
|
+
error?: string;
|
|
25
|
+
steps?: string[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The cloud "replay": validate that a drafted recipe's selectors extract the
|
|
29
|
+
* expected value from a captured response, inside the TEE — `POST {apiUrl}
|
|
30
|
+
* /reclaim/validate-extraction`. Reuses the prover's own redaction engine, so
|
|
31
|
+
* a pass means the selectors won't diverge at proof time. No proof/secrets.
|
|
32
|
+
*/
|
|
33
|
+
export declare function popcornValidateExtraction(opts: {
|
|
34
|
+
apiUrl: string;
|
|
35
|
+
responseBody: string;
|
|
36
|
+
expectedValue: string;
|
|
37
|
+
xPath?: string;
|
|
38
|
+
jsonPath?: string;
|
|
39
|
+
regex?: string;
|
|
40
|
+
fetchImpl?: typeof fetch;
|
|
41
|
+
}): Promise<ValidateExtractionResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Prove a single request through the Popcorn TEE. Returns the shared
|
|
44
|
+
* {@link ProofResult}; on any failure `verified` is false and `error` carries
|
|
45
|
+
* the reason (never throws for an expected proof failure).
|
|
46
|
+
*/
|
|
47
|
+
export declare function popcornProve(opts: PopcornProveOptions): Promise<ProofResult>;
|