@reclaimprotocol/agent 0.1.22 → 0.1.24
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 +55 -20
- package/lib/authoring/backend.d.ts +13 -10
- package/lib/authoring/tools.js +106 -9
- package/lib/cdp/browser-proxy.d.ts +78 -0
- package/lib/cdp/browser-proxy.js +186 -0
- package/lib/cdp/capture-engine.js +8 -7
- package/lib/cdp/client.d.ts +10 -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/page.d.ts +20 -0
- package/lib/live/page.js +134 -0
- package/lib/live/tunnel.d.ts +23 -0
- package/lib/live/tunnel.js +120 -0
- package/lib/live/viewer.d.ts +28 -0
- package/lib/live/viewer.js +232 -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 +101 -38
- package/lib/mcp/start.js +4 -3
- package/lib/mcp/tools/agent/analyze.js +5 -1
- package/lib/mcp/tools/agent/attach.d.ts +8 -1
- package/lib/mcp/tools/agent/attach.js +166 -22
- package/lib/mcp/tools/agent/build.d.ts +13 -8
- package/lib/mcp/tools/agent/build.js +22 -11
- 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/live-view.d.ts +21 -0
- package/lib/mcp/tools/agent/live-view.js +153 -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 +29 -3
- package/lib/mcp/tools/agent/proxy.d.ts +3 -0
- package/lib/mcp/tools/agent/proxy.js +199 -0
- package/lib/mcp/tools/agent/publish.js +49 -77
- package/lib/mcp/tools/agent/session.d.ts +2 -1
- package/lib/mcp/tools/agent/session.js +26 -7
- package/lib/mcp/tools/agent/shared.js +17 -8
- package/lib/mcp/tools/authenticate/authenticate.d.ts +11 -0
- package/lib/mcp/tools/authenticate/authenticate.js +143 -121
- package/lib/mcp/tools/authenticate/builder-access.d.ts +8 -3
- package/lib/mcp/tools/authenticate/builder-access.js +8 -3
- package/lib/mcp/tools/mode/mode.d.ts +1 -1
- package/lib/mcp/tools/mode/mode.js +26 -7
- package/lib/old/client.d.ts +9 -0
- package/lib/old/client.js +19 -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 +20 -8
- package/lib/old/to-register.js +7 -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/me-providers.js +3 -1
- package/lib/old/tools/publish.d.ts +1 -1
- package/lib/old/tools/publish.js +132 -129
- 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 +36 -0
- package/lib/proof/page-replay.js +76 -0
- package/lib/proof/pod-prover.d.ts +47 -0
- package/lib/proof/pod-prover.js +155 -0
- package/lib/proof/replay.d.ts +28 -0
- package/lib/proof/replay.js +39 -18
- package/lib/provider/dom-xpath.js +11 -9
- package/lib/provider/draft.d.ts +13 -8
- package/lib/provider/draft.js +47 -13
- 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 +122 -12
- package/lib/provider/secrets.d.ts +3 -3
- package/lib/provider/secrets.js +3 -3
- package/lib/provider/to-version.d.ts +12 -9
- package/lib/provider/to-version.js +16 -4
- package/lib/tools/registry.d.ts +5 -5
- package/lib/tools/registry.js +5 -5
- package/package.json +4 -3
- package/samples/demo-server/README.md +7 -6
- package/skill/SKILL.builder.md +356 -189
- package/skill/SKILL.common.md +314 -79
- package/skill/SKILL.old.md +340 -155
- package/skill/builder-mode.md +58 -17
- package/skill/hash-validation.md +170 -0
- package/skill/interception.md +235 -0
- package/skill/js-sdk-integration.md +13 -7
- package/skill/old-mode.md +53 -12
- package/skill/user-script.md +61 -0
- package/src/authoring/backend.ts +13 -10
- package/src/authoring/tools.ts +128 -9
- package/src/cdp/capture-engine.ts +8 -7
- package/src/cdp/client.ts +8 -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/page.ts +145 -0
- package/src/live/tunnel.ts +157 -0
- package/src/live/viewer.ts +293 -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 +121 -48
- package/src/mcp/start.ts +4 -3
- package/src/mcp/tools/agent/analyze.ts +5 -1
- package/src/mcp/tools/agent/attach.ts +194 -22
- package/src/mcp/tools/agent/build.ts +26 -15
- 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/live-view.ts +198 -0
- package/src/mcp/tools/agent/pod-proof.ts +90 -0
- package/src/mcp/tools/agent/propose.ts +31 -3
- package/src/mcp/tools/agent/publish.ts +54 -78
- package/src/mcp/tools/agent/session.ts +26 -5
- package/src/mcp/tools/agent/shared.ts +19 -8
- package/src/mcp/tools/authenticate/authenticate.ts +167 -165
- package/src/mcp/tools/authenticate/builder-access.ts +8 -3
- package/src/mcp/tools/mode/mode.ts +28 -7
- package/src/old/client.ts +30 -1
- package/src/old/instructions.ts +4 -10
- package/src/old/login-cdp.ts +50 -6
- package/src/old/to-register.ts +28 -8
- 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/me-providers.ts +3 -1
- package/src/old/tools/publish.ts +140 -130
- 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 +131 -0
- package/src/proof/pod-prover.ts +231 -0
- package/src/proof/replay.ts +60 -19
- package/src/provider/dom-xpath.ts +11 -9
- package/src/provider/draft.ts +56 -13
- package/src/provider/injection-doc.ts +37 -24
- package/src/provider/match-redaction-warning.ts +3 -3
- package/src/provider/matcher.ts +151 -10
- package/src/provider/secrets.ts +3 -3
- package/src/provider/to-version.ts +30 -13
- package/src/tools/registry.ts +5 -5
- package/skill/injection-api.md +0 -335
package/lib/old/to-register.d.ts
CHANGED
|
@@ -26,7 +26,8 @@ export interface OldProviderOpts {
|
|
|
26
26
|
/** Page-injection script — the devtools name for the builder's
|
|
27
27
|
* `webSettings.jsUserScripts`. Top-level on register, nested under
|
|
28
28
|
* `providerConfig` on config (add-version). The backend rejects a few
|
|
29
|
-
* deprecated injection APIs (
|
|
29
|
+
* deprecated injection APIs (for example, `window.payloadData`) with a
|
|
30
|
+
* 400. */
|
|
30
31
|
customInjection?: string;
|
|
31
32
|
/** Accepted at register too (unlike the four fields below, which the
|
|
32
33
|
* backend only accepts on config/add-version). */
|
|
@@ -51,13 +52,24 @@ export interface OldProviderOpts {
|
|
|
51
52
|
* field from the request body. Free-form JSON. */
|
|
52
53
|
extensionConfig?: unknown;
|
|
53
54
|
/** Provider-level `disableRequestReplay` (HAWKEYE document replay skip).
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* `
|
|
59
|
-
* .
|
|
55
|
+
* The publish tool always forces this `true` — there is no author-facing
|
|
56
|
+
* way to enable document replay. Config (add-version) ONLY: the register
|
|
57
|
+
* endpoint hardcodes it to false regardless of what's sent, so the
|
|
58
|
+
* publish tool always follows a register up with an add-version call to
|
|
59
|
+
* actually apply it (see `old/tools/publish.ts`). The builder backend's
|
|
60
|
+
* inverse-named equivalent, `webSettings.clientOptions.inapp
|
|
61
|
+
* .interceptorOptions.isDocumentRequestReplayEnabled`, is likewise always
|
|
62
|
+
* force-disabled by `providerToCreateVersionRequest`. */
|
|
60
63
|
disableRequestReplay?: boolean;
|
|
64
|
+
/** Interception mechanism — `NONE` (the publish tool's default) for the
|
|
65
|
+
* standard capture→replay flow; `HAWKEYE`/`MSWJS`/`XHOOK`/`CDP` for a
|
|
66
|
+
* genuine live-interception provider. Old-devtools calls this
|
|
67
|
+
* `injectionType`; builder's equivalent is `webSettings.clientOptions
|
|
68
|
+
* .inapp.interceptorOptions.interceptorType` (no `NONE` value there —
|
|
69
|
+
* omitting the whole object is builder's no-interception signal
|
|
70
|
+
* instead). See `old/client.ts`'s `RegisterProviderBody.injectionType`
|
|
71
|
+
* doc for the register-persistence caveat. */
|
|
72
|
+
injectionType?: 'NONE' | 'MSWJS' | 'XHOOK' | 'CDP' | 'HAWKEYE';
|
|
61
73
|
}
|
|
62
74
|
interface OldResponseMatch {
|
|
63
75
|
value: string;
|
|
@@ -118,7 +130,7 @@ export interface SemverTriplet {
|
|
|
118
130
|
/**
|
|
119
131
|
* Pull `{major,minor,patch}` triplets out of a `/versions` response, tolerant
|
|
120
132
|
* of the exact envelope (array, `{ providerVersions: [...] }`, `{ items }`,
|
|
121
|
-
|
|
133
|
+
*, and so on). Each entry's `version` is the triplet.
|
|
122
134
|
*/
|
|
123
135
|
export declare function extractVersions(resp: unknown): SemverTriplet[];
|
|
124
136
|
/**
|
package/lib/old/to-register.js
CHANGED
|
@@ -133,6 +133,9 @@ export function providerToRegisterBody(providers, opts) {
|
|
|
133
133
|
if (opts.stepsToFollow !== undefined) {
|
|
134
134
|
body.stepsToFollow = opts.stepsToFollow;
|
|
135
135
|
}
|
|
136
|
+
if (opts.injectionType !== undefined) {
|
|
137
|
+
body.injectionType = opts.injectionType;
|
|
138
|
+
}
|
|
136
139
|
return body;
|
|
137
140
|
}
|
|
138
141
|
/** Body for `POST /api/providers/:providerId/config` — adds a new version to
|
|
@@ -173,12 +176,15 @@ export function providerToConfigBody(providers, opts, version, versionInfo) {
|
|
|
173
176
|
if (opts.disableRequestReplay !== undefined) {
|
|
174
177
|
providerConfig.disableRequestReplay = opts.disableRequestReplay;
|
|
175
178
|
}
|
|
179
|
+
if (opts.injectionType !== undefined) {
|
|
180
|
+
providerConfig.injectionType = opts.injectionType;
|
|
181
|
+
}
|
|
176
182
|
return { providerConfig, version, versionInfo };
|
|
177
183
|
}
|
|
178
184
|
/**
|
|
179
185
|
* Pull `{major,minor,patch}` triplets out of a `/versions` response, tolerant
|
|
180
186
|
* of the exact envelope (array, `{ providerVersions: [...] }`, `{ items }`,
|
|
181
|
-
|
|
187
|
+
*, and so on). Each entry's `version` is the triplet.
|
|
182
188
|
*/
|
|
183
189
|
export function extractVersions(resp) {
|
|
184
190
|
const list = pickArray(resp);
|
|
@@ -36,6 +36,11 @@ export function authenticateTool(client) {
|
|
|
36
36
|
'and closes the tab. A previously stored identity that is still ' +
|
|
37
37
|
'valid is reused first (pass `useBrowser: true` to force a fresh ' +
|
|
38
38
|
'login). \n\n' +
|
|
39
|
+
'EXPECT THIS TO TAKE A WHILE ON A FIRST RUN: a fresh Chrome ' +
|
|
40
|
+
'profile downloads the dashboard cold, so tell the developer it is ' +
|
|
41
|
+
'loading and that the window is waiting for them — do not re-run ' +
|
|
42
|
+
'the tool while it is still waiting. It polls for up to 6 minutes ' +
|
|
43
|
+
'and reports whether the page ever became interactive.\n\n' +
|
|
39
44
|
'Manual overrides:\n' +
|
|
40
45
|
'- `token`: paste a Firebase ID token (skips the browser).\n' +
|
|
41
46
|
'- `ethAddress`: an `eth:0x…` / `0x…` uid for an already-provisioned ' +
|
|
@@ -61,7 +66,10 @@ export function authenticateTool(client) {
|
|
|
61
66
|
},
|
|
62
67
|
timeoutMs: {
|
|
63
68
|
type: 'number',
|
|
64
|
-
description: 'How long to wait for sign-in, in ms (default
|
|
69
|
+
description: 'How long to wait for sign-in, in ms (default 360000, i.e. 6 '
|
|
70
|
+
+ 'minutes). A fresh Chrome profile loads the dashboard cold, '
|
|
71
|
+
+ 'which can take tens of seconds before the form is usable — '
|
|
72
|
+
+ 'that time comes out of this budget.',
|
|
65
73
|
},
|
|
66
74
|
useBrowser: {
|
|
67
75
|
type: 'boolean',
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isBoom } from '@hapi/boom';
|
|
2
2
|
import { defineTool } from "../../mcp/server.js";
|
|
3
3
|
/** Best-effort call: resolve to the response, or to an error string instead
|
|
4
|
-
* of throwing — one endpoint 404ing (
|
|
5
|
-
* hide a result the other endpoint DID have. */
|
|
4
|
+
* of throwing — one endpoint 404ing (for example, a bad `versionNumber`)
|
|
5
|
+
* shouldn't hide a result the other endpoint DID have. */
|
|
6
6
|
async function attempt(label, call) {
|
|
7
7
|
try {
|
|
8
8
|
return { ok: true, value: await call() };
|
|
@@ -44,8 +44,9 @@ export function getProviderInfoTool(client) {
|
|
|
44
44
|
'computed `isScriptRequestingClaim` flag). Read `provider` here ' +
|
|
45
45
|
'BEFORE create_provider_version_from_capture so you can pass the ' +
|
|
46
46
|
'whole existing config back — that tool always creates a new ' +
|
|
47
|
-
'version and carries nothing forward. One endpoint failing (
|
|
48
|
-
'an invalid `versionNumber`) is reported under `errors`
|
|
47
|
+
'version and carries nothing forward. One endpoint failing (for ' +
|
|
48
|
+
'example, an invalid `versionNumber`) is reported under `errors` ' +
|
|
49
|
+
'without ' +
|
|
49
50
|
'hiding a result the other endpoint did return.',
|
|
50
51
|
inputSchema: {
|
|
51
52
|
type: 'object',
|
|
@@ -56,7 +57,7 @@ export function getProviderInfoTool(client) {
|
|
|
56
57
|
},
|
|
57
58
|
versionNumber: {
|
|
58
59
|
type: 'string',
|
|
59
|
-
description: 'Specific version,
|
|
60
|
+
description: 'Specific version, for example, "1.0.2". Omit for the ' +
|
|
60
61
|
"provider's current latest version.",
|
|
61
62
|
},
|
|
62
63
|
},
|
|
@@ -18,8 +18,9 @@ export function issueAppCredentialsTool(client) {
|
|
|
18
18
|
'starts UNLINKED and sandboxed (100 sessions) — call ' +
|
|
19
19
|
'link_app_to_account to attach it to your dashboard account and ' +
|
|
20
20
|
'check_app_status to check its state. Store `appSecret` like a ' +
|
|
21
|
-
'password (
|
|
22
|
-
'is returned once and cannot be
|
|
21
|
+
'password (for example, in a gitignored .env as ' +
|
|
22
|
+
'RECLAIM_APP_SECRET) — it is returned once and cannot be ' +
|
|
23
|
+
'recovered from the server.',
|
|
23
24
|
inputSchema: { type: 'object', properties: {} },
|
|
24
25
|
}, async () => {
|
|
25
26
|
const { appId, appSecret } = await client.issueCredentials();
|
|
@@ -13,7 +13,9 @@ export function getMeProvidersTool(client) {
|
|
|
13
13
|
'first). Returns provider metadata including each `providerId` — ' +
|
|
14
14
|
'pass one back to create_provider_version_from_capture to publish a ' +
|
|
15
15
|
'new version of that provider instead of creating a duplicate. ' +
|
|
16
|
-
'Requires reclaim_authenticate first
|
|
16
|
+
'Requires reclaim_authenticate (old-devtools login) first — this ' +
|
|
17
|
+
'is separate from authenticate_builder/Builder auth, which does ' +
|
|
18
|
+
'not authorize this call. Check status with get_devtools_mode.',
|
|
17
19
|
inputSchema: {
|
|
18
20
|
type: 'object',
|
|
19
21
|
properties: {
|
|
@@ -4,7 +4,7 @@ import type { ReclaimOldClient } from '../client.ts';
|
|
|
4
4
|
/**
|
|
5
5
|
* Publish a drafted provider to the OLD devtools backend. Keeps the builder
|
|
6
6
|
* tool NAME (`create_provider_version_from_capture`) so the skill flow is
|
|
7
|
-
* unchanged, but the
|
|
7
|
+
* unchanged, but the behavior differs:
|
|
8
8
|
*
|
|
9
9
|
* - WITHOUT `providerId` → `POST /api/providers/register`: creates a
|
|
10
10
|
* brand-new provider + version 1.0.0. Re-running creates a DUPLICATE.
|
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,54 +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
|
-
'together.
|
|
67
|
-
'
|
|
68
|
-
'Omit `providerId` to REGISTER A NEW provider (creates it +
|
|
69
|
-
'1.0.0
|
|
70
|
-
'get_me_providers) to add a NEW VERSION to
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
'
|
|
74
|
-
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
'
|
|
79
|
-
'
|
|
80
|
-
'
|
|
81
|
-
'
|
|
82
|
-
'
|
|
83
|
-
'
|
|
84
|
-
'
|
|
85
|
-
'`
|
|
86
|
-
'
|
|
87
|
-
'
|
|
88
|
-
|
|
89
|
-
'
|
|
90
|
-
'
|
|
91
|
-
'values plus your change) back into this call. ' +
|
|
92
|
-
'`allowedInjectedRequestData`/`useIncognitoWebview`/' +
|
|
93
|
-
'`extensionConfig` only take effect on add-version — the register ' +
|
|
94
|
-
'endpoint (no `providerId`) ignores them. `disableRequestReplay` ' +
|
|
95
|
-
'is also add-version-only, but when it is true the tool follows ' +
|
|
96
|
-
'a register up with an add-version call automatically so it takes ' +
|
|
97
|
-
'effect on new providers too. Per-request fields you may set on ' +
|
|
98
|
-
'`provider`/`providers`: `credentials` (omit/same-origin/include, ' +
|
|
99
|
-
'default include), `urlType` (REGEX/CONSTANT/TEMPLATE, default ' +
|
|
100
|
-
'derived from {{placeholders}}), and `isOptional` on each ' +
|
|
101
|
-
'responseMatch (default false). \n\n' +
|
|
102
|
-
'Captured requests must be GET/POST. OPRF redactions are supported. ' +
|
|
103
|
-
'On success, if a browser is still attached, the response\'s ' +
|
|
104
|
-
'`_notes` reminds you to confirm with the developer before ' +
|
|
105
|
-
'calling `dispose_browser` — never close it unprompted, they ' +
|
|
106
|
-
'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" }).',
|
|
107
91
|
inputSchema: {
|
|
108
92
|
type: 'object',
|
|
109
93
|
properties: {
|
|
@@ -205,15 +189,11 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
205
189
|
},
|
|
206
190
|
customInjection: {
|
|
207
191
|
type: 'string',
|
|
208
|
-
description:
|
|
209
|
-
'
|
|
210
|
-
'
|
|
211
|
-
'(window.
|
|
212
|
-
'
|
|
213
|
-
'only for rare edge cases, not navigation. The backend rejects ' +
|
|
214
|
-
'a few deprecated injection APIs (e.g. window.payloadData, ' +
|
|
215
|
-
'window.ReclaimInjected) with a 400. Guide:\n\n' +
|
|
216
|
-
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.',
|
|
217
197
|
},
|
|
218
198
|
userAgent: {
|
|
219
199
|
type: 'object',
|
|
@@ -230,39 +210,15 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
230
210
|
},
|
|
231
211
|
allowedInjectedRequestData: {
|
|
232
212
|
type: 'array',
|
|
233
|
-
description: 'Extra requests the customInjection script is allowed to '
|
|
234
|
-
'fire (
|
|
235
|
-
'
|
|
236
|
-
'
|
|
237
|
-
|
|
238
|
-
'
|
|
239
|
-
'
|
|
240
|
-
'
|
|
241
|
-
|
|
242
|
-
'the "bodySniff" section of the customInjection field\'s guide ' +
|
|
243
|
-
'for the exact mechanics and a worked example. ' +
|
|
244
|
-
'⚠️ BEFORE populating this to gate ' +
|
|
245
|
-
'`verifyProof(proof, { providerId })`: this whole entry (url, ' +
|
|
246
|
-
'method, body, responseMatches, responseRedactions) feeds a ' +
|
|
247
|
-
'client-side hash-equality check, and `url` is hashed VERBATIM ' +
|
|
248
|
-
'— no regex/template resolution, even with `urlType: REGEX` or ' +
|
|
249
|
-
'`TEMPLATE`. If the real captured URL contains ANY per-session ' +
|
|
250
|
-
'part (a tracking nonce, CSRF token, cache-busting timestamp), ' +
|
|
251
|
-
'no declared spec can EVER hash-match a real proof, no matter ' +
|
|
252
|
-
'how correct the rest of this entry is — populating' +
|
|
253
|
-
'it for such ' +
|
|
254
|
-
'a provider makes verifyProof reject every real proof,' +
|
|
255
|
-
'which is ' +
|
|
256
|
-
'worse than leaving this field empty. Diff the same endpoint\'s' +
|
|
257
|
-
' captured URL across two separate sessions before wiring this ' +
|
|
258
|
-
'up. If provider-hash validation keeps causing problems ' +
|
|
259
|
-
'(unstable url, or any other persistent mismatch), the ' +
|
|
260
|
-
'fallback on the verifying side is `verifyProof(proof, { ' +
|
|
261
|
-
'dangerouslyDisableContentValidation: true })` — trusts only ' +
|
|
262
|
-
'the attestor\'s signature, skips the hash-equality check ' +
|
|
263
|
-
'entirely; see the "Provider-hash validation" section of the ' +
|
|
264
|
-
'customInjection field\'s guide for the full mechanics and ' +
|
|
265
|
-
'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,
|
|
266
222
|
items: {
|
|
267
223
|
type: 'object',
|
|
268
224
|
properties: {
|
|
@@ -282,7 +238,8 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
282
238
|
'body at all (skip only for a genuinely bodyless ' +
|
|
283
239
|
'request, typically GET). If the real body is FIXED ' +
|
|
284
240
|
'(identical for every user/run), put that literal body ' +
|
|
285
|
-
'text here verbatim. If only PART of it varies (
|
|
241
|
+
'text here verbatim. If only PART of it varies (for ' +
|
|
242
|
+
'example, ' +
|
|
286
243
|
'`{"request":1,"type":"user_info","id":"12345"}` where ' +
|
|
287
244
|
'only `id` differs per user), template ONLY that part: ' +
|
|
288
245
|
'`{"request":1,"type":"user_info",' +
|
|
@@ -305,7 +262,7 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
305
262
|
'reproduces the real captured request body ' +
|
|
306
263
|
'byte-for-byte. Fallback if per-field templating keeps ' +
|
|
307
264
|
'mismatching (more fields vary than expected, unstable ' +
|
|
308
|
-
'key order,
|
|
265
|
+
'key order, and so on) and you can\'t pin down every ' +
|
|
309
266
|
'variable field: template the WHOLE body as one ' +
|
|
310
267
|
'placeholder instead, `{{REQ_BODY_GRD}}` — the `GRD` ' +
|
|
311
268
|
'suffix makes it a greedy match (captures everything) ' +
|
|
@@ -322,7 +279,7 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
322
279
|
'`value` must literally appear (or match, if `regex`) ' +
|
|
323
280
|
'somewhere in the response body for the claim to be ' +
|
|
324
281
|
'accepted; it commonly embeds one or more ' +
|
|
325
|
-
'`{{paramName}}` extraction placeholders (
|
|
282
|
+
'`{{paramName}}` extraction placeholders (for example, ' +
|
|
326
283
|
'`"name":"{{name_0}}"`) whose real value is redacted ' +
|
|
327
284
|
'out and supplied separately as a witness/extracted ' +
|
|
328
285
|
'param. Use `${var}` (not `{{var}}`) inside this string ' +
|
|
@@ -337,7 +294,8 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
337
294
|
description: 'Each item: `{ jsonPath?: string, xPath?: string, ' +
|
|
338
295
|
'regex?: string, hash?: string }`. Identifies WHICH ' +
|
|
339
296
|
'part of the response the matching `{{paramName}}` in ' +
|
|
340
|
-
'`responseMatches` actually redacts
|
|
297
|
+
'`responseMatches` actually redacts or extracts — for ' +
|
|
298
|
+
'example, ' +
|
|
341
299
|
'`jsonPath: "$.data.items[0].name"` for a JSON response. ' +
|
|
342
300
|
'Order/count should line up with `responseMatches`\' ' +
|
|
343
301
|
'placeholders one-to-one for a typical claim.',
|
|
@@ -388,13 +346,34 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
388
346
|
description: 'Free-form JSON passed through to the client. Add-version ' +
|
|
389
347
|
'ONLY.',
|
|
390
348
|
},
|
|
349
|
+
injectionType: {
|
|
350
|
+
type: 'string',
|
|
351
|
+
enum: ['NONE', 'MSWJS', 'XHOOK', 'CDP', 'HAWKEYE'],
|
|
352
|
+
description: 'Interception mechanism for this version. Omit to leave it ' +
|
|
353
|
+
'unset — the devtools backend\'s own column default ' +
|
|
354
|
+
'(`HAWKEYE`) applies, which is inert and harmless for the ' +
|
|
355
|
+
'standard capture→replay flow with no interceptor script ' +
|
|
356
|
+
'installed. Only set `HAWKEYE`/`MSWJS`/`XHOOK` when you are ' +
|
|
357
|
+
'ALSO supplying a `customInjection` script that calls ' +
|
|
358
|
+
'`window.reclaimInterceptor.addResponseMiddleware(...)` for ' +
|
|
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
|
+
},
|
|
391
366
|
disableRequestReplay: {
|
|
392
367
|
type: 'boolean',
|
|
393
|
-
description: '
|
|
394
|
-
'
|
|
395
|
-
'
|
|
396
|
-
'
|
|
397
|
-
'
|
|
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.',
|
|
398
377
|
},
|
|
399
378
|
},
|
|
400
379
|
required: ['initialUrl'],
|
|
@@ -429,7 +408,13 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
429
408
|
stepsToFollow: args.stepsToFollow,
|
|
430
409
|
useIncognitoWebview: args.useIncognitoWebview,
|
|
431
410
|
extensionConfig: args.extensionConfig,
|
|
432
|
-
|
|
411
|
+
// Author-settable, no forced default — the backend's own HAWKEYE
|
|
412
|
+
// column default applies when omitted, same as before this field
|
|
413
|
+
// existed at all.
|
|
414
|
+
injectionType: args.injectionType,
|
|
415
|
+
// Author-settable; defaults to disabled (see tool description).
|
|
416
|
+
// Only meaningful for HAWKEYE/MSWJS/XHOOK — inert for CDP.
|
|
417
|
+
disableRequestReplay: args.disableRequestReplay ?? true,
|
|
433
418
|
allowedInjectedRequestData: args.allowedInjectedRequestData
|
|
434
419
|
? injectedRequestDataFrom(args.allowedInjectedRequestData)
|
|
435
420
|
: undefined
|
|
@@ -468,11 +453,12 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
468
453
|
'every page load (before navigating to initialUrl), matching ' +
|
|
469
454
|
'the builder\'s jsUserScripts.');
|
|
470
455
|
}
|
|
471
|
-
// disableRequestReplay is honored ONLY on add-version
|
|
472
|
-
// register
|
|
473
|
-
//
|
|
474
|
-
//
|
|
475
|
-
|
|
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).
|
|
476
462
|
const REGISTER_IGNORED_KEYS = [
|
|
477
463
|
'allowedInjectedRequestData',
|
|
478
464
|
'useIncognitoWebview',
|
|
@@ -484,38 +470,55 @@ export function createVersionFromCaptureTool(client, attachRef) {
|
|
|
484
470
|
notes.push(`${ignoredOnRegister.join(', ')} ` +
|
|
485
471
|
`${ignoredOnRegister.length > 1 ? 'are' : 'is'} ` +
|
|
486
472
|
'ignored on register (no providerId) — the devtools backend only ' +
|
|
487
|
-
'reads them when adding a version. ' +
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
'created to set disableRequestReplay.'
|
|
491
|
-
: 'Publish once to create the provider, then call this ' +
|
|
492
|
-
'again WITH the returned providerId to set them.'));
|
|
473
|
+
'reads them when adding a version. They were applied by the ' +
|
|
474
|
+
'automatic follow-up version this tool always creates to apply ' +
|
|
475
|
+
'disableRequestReplay.');
|
|
493
476
|
}
|
|
494
477
|
const body = providerToRegisterBody(providers, opts);
|
|
495
478
|
const registered = await client.registerProvider(body);
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
479
|
+
const newProviderId = extractProviderId(registered);
|
|
480
|
+
if (newProviderId) {
|
|
481
|
+
// The provider already exists as of the register call above —
|
|
482
|
+
// a failure past this point must NOT reject the tool and
|
|
483
|
+
// discard `registered`/`newProviderId`, or a retry without
|
|
484
|
+
// `providerId` would register a DUPLICATE provider. Catch and
|
|
485
|
+
// warn instead, telling the caller to resume WITH this
|
|
486
|
+
// providerId.
|
|
487
|
+
try {
|
|
499
488
|
const versionsResp = await client.listVersions(newProviderId);
|
|
500
489
|
const followVersion = bumpPatchString(extractVersions(versionsResp));
|
|
501
|
-
const configBody = providerToConfigBody(providers,
|
|
490
|
+
const configBody = providerToConfigBody(providers, opts, followVersion, DEFAULT_VERSION_INFO);
|
|
502
491
|
await client.updateProviderConfig(newProviderId, configBody);
|
|
503
|
-
notes.push(
|
|
504
|
-
`
|
|
505
|
-
|
|
506
|
-
|
|
492
|
+
notes.push(`Created an automatic follow-up version (${followVersion}) to ` +
|
|
493
|
+
`apply disableRequestReplay (${opts.disableRequestReplay})` +
|
|
494
|
+
(opts.injectionType !== undefined
|
|
495
|
+
? ` and set injectionType (${opts.injectionType})`
|
|
496
|
+
: '') +
|
|
497
|
+
' — the register endpoint ignores/may ignore those fields, so ' +
|
|
498
|
+
'every fresh register gets one. It also landed any other ' +
|
|
499
|
+
'register-ignored fields you passed.');
|
|
507
500
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
501
|
+
catch (err) {
|
|
502
|
+
const detail = isBoom(err) ? err.message : String(err);
|
|
503
|
+
notes.push(`Provider ${newProviderId} WAS created, but the automatic ` +
|
|
504
|
+
`follow-up version (to force-disable document replay${opts.injectionType !== undefined
|
|
505
|
+
? ' and set injectionType'
|
|
506
|
+
: ''}) failed: ${detail}. Do NOT retry without providerId — that ` +
|
|
507
|
+
'would register a duplicate. Instead, re-run ' +
|
|
508
|
+
'create_provider_version_from_capture WITH ' +
|
|
509
|
+
`providerId: "${newProviderId}" to add the follow-up version.`);
|
|
513
510
|
}
|
|
514
511
|
}
|
|
512
|
+
else {
|
|
513
|
+
notes.push('Could not apply disableRequestReplay: the ' +
|
|
514
|
+
'register response did not include the new providerId. Call ' +
|
|
515
|
+
'this tool again WITH `providerId` to create a version that ' +
|
|
516
|
+
'applies them.');
|
|
517
|
+
}
|
|
515
518
|
return withNotes(registered);
|
|
516
519
|
}
|
|
517
520
|
// New version of an existing provider — pick the next patch above
|
|
518
|
-
// the highest existing version. A provider you don't own (
|
|
521
|
+
// the highest existing version. A provider you don't own (for example, a
|
|
519
522
|
// public one) fails here with 401/403/404; surface the register-a-copy
|
|
520
523
|
// workaround instead of a bare permission error.
|
|
521
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. */
|