@reclaimprotocol/agent 0.1.1-dev.1 → 0.1.1

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.
Files changed (201) hide show
  1. package/README.md +1 -1
  2. package/lib/cdp/capture-engine.d.ts +66 -0
  3. package/lib/cdp/capture-engine.js +153 -0
  4. package/lib/cdp/capture.d.ts +9 -20
  5. package/lib/cdp/capture.js +14 -138
  6. package/lib/cdp/index.d.ts +3 -0
  7. package/lib/cdp/index.js +6 -0
  8. package/lib/config/store.d.ts +7 -6
  9. package/lib/config/store.js +2 -2
  10. package/lib/index.d.ts +2 -2
  11. package/lib/index.js +1 -1
  12. package/lib/mcp/api/operations.gen.d.ts +101 -45
  13. package/lib/mcp/api/operations.gen.js +996 -126
  14. package/lib/mcp/api/to-zod.d.ts +24 -0
  15. package/lib/mcp/api/to-zod.js +94 -0
  16. package/lib/mcp/api/tools.js +1 -1
  17. package/lib/mcp/credentials/authenticate.d.ts +3 -0
  18. package/lib/mcp/{tools/credentials → credentials}/authenticate.js +3 -3
  19. package/lib/mcp/credentials/build.d.ts +5 -0
  20. package/lib/mcp/credentials/build.js +18 -0
  21. package/lib/mcp/{tools/credentials → credentials}/cache.d.ts +9 -9
  22. package/lib/mcp/{tools/credentials → credentials}/cache.js +36 -19
  23. package/lib/mcp/credentials/import.d.ts +2 -0
  24. package/lib/mcp/{tools/credentials → credentials}/import.js +2 -2
  25. package/lib/mcp/credentials/issue.d.ts +2 -0
  26. package/lib/mcp/{tools/credentials → credentials}/issue.js +4 -4
  27. package/lib/mcp/credentials/keypair.d.ts +17 -0
  28. package/lib/mcp/credentials/keypair.js +48 -0
  29. package/lib/mcp/credentials/link.d.ts +3 -0
  30. package/lib/mcp/credentials/link.js +107 -0
  31. package/lib/mcp/{tools/credentials → credentials}/list-cached.d.ts +1 -1
  32. package/lib/mcp/{tools/credentials → credentials}/list-cached.js +5 -5
  33. package/lib/mcp/credentials/owner-key.d.ts +23 -0
  34. package/lib/mcp/credentials/owner-key.js +58 -0
  35. package/lib/mcp/credentials/paths.d.ts +12 -0
  36. package/lib/mcp/credentials/paths.js +35 -0
  37. package/lib/mcp/credentials/poll.d.ts +27 -0
  38. package/lib/mcp/credentials/poll.js +61 -0
  39. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.d.ts +1 -1
  40. package/lib/mcp/{tools/credentials → credentials}/resolve-owner-key.js +2 -2
  41. package/lib/mcp/credentials/session-cache.d.ts +14 -0
  42. package/lib/mcp/credentials/session-cache.js +42 -0
  43. package/lib/mcp/{tools/credentials → credentials}/status.d.ts +1 -1
  44. package/lib/mcp/credentials/status.js +76 -0
  45. package/lib/mcp/instructions.d.ts +1 -0
  46. package/lib/mcp/instructions.js +11 -0
  47. package/lib/mcp/register.d.ts +38 -0
  48. package/lib/mcp/register.js +80 -0
  49. package/lib/mcp/server.d.ts +2 -2
  50. package/lib/mcp/server.js +3 -3
  51. package/lib/mcp/start.js +10 -4
  52. package/lib/mcp/tools/agent/build.js +2 -15
  53. package/lib/mcp/tools/agent/index.d.ts +2 -0
  54. package/lib/mcp/tools/agent/index.js +3 -0
  55. package/lib/mcp/tools/agent/proof.js +1 -6
  56. package/lib/mcp/tools/agent/propose.js +13 -2
  57. package/lib/mcp/tools/agent/publish.js +10 -2
  58. package/lib/mcp/tools/agent/replay.js +0 -5
  59. package/lib/mcp/tools/analyze.d.ts +3 -0
  60. package/lib/mcp/tools/analyze.js +26 -0
  61. package/lib/mcp/tools/attach.d.ts +11 -0
  62. package/lib/mcp/tools/attach.js +72 -0
  63. package/lib/mcp/tools/authenticate/authenticate.js +107 -0
  64. package/lib/mcp/tools/authenticate/build.d.ts +15 -0
  65. package/lib/mcp/tools/authenticate/build.js +28 -0
  66. package/lib/mcp/tools/authenticate/decrypt-key.d.ts +32 -0
  67. package/lib/mcp/tools/authenticate/decrypt-key.js +49 -0
  68. package/lib/mcp/tools/authenticate/eth-key.d.ts +38 -0
  69. package/lib/mcp/tools/authenticate/eth-key.js +130 -0
  70. package/lib/mcp/tools/authenticate/import.js +57 -0
  71. package/lib/mcp/tools/authenticate/index.d.ts +2 -0
  72. package/lib/mcp/tools/authenticate/index.js +4 -0
  73. package/lib/mcp/tools/authenticate/issue.js +42 -0
  74. package/lib/mcp/tools/authenticate/resolve-owner-key.d.ts +13 -0
  75. package/lib/mcp/tools/authenticate/resolve-owner-key.js +53 -0
  76. package/lib/mcp/tools/capture.d.ts +10 -0
  77. package/lib/mcp/tools/capture.js +142 -0
  78. package/lib/mcp/tools/eval.d.ts +5 -0
  79. package/lib/mcp/tools/eval.js +127 -0
  80. package/lib/mcp/tools/find.d.ts +3 -0
  81. package/lib/mcp/tools/find.js +60 -0
  82. package/lib/mcp/tools/index.d.ts +3 -0
  83. package/lib/mcp/tools/index.js +6 -0
  84. package/lib/mcp/tools/owner-key.d.ts +2 -0
  85. package/lib/mcp/tools/owner-key.js +63 -0
  86. package/lib/mcp/tools/proof.d.ts +3 -0
  87. package/lib/mcp/tools/proof.js +214 -0
  88. package/lib/mcp/tools/propose.d.ts +9 -0
  89. package/lib/mcp/tools/propose.js +75 -0
  90. package/lib/mcp/tools/publish.d.ts +3 -0
  91. package/lib/mcp/tools/publish.js +59 -0
  92. package/lib/mcp/tools/replay.d.ts +3 -0
  93. package/lib/mcp/tools/replay.js +46 -0
  94. package/lib/mcp/tools/session.d.ts +10 -0
  95. package/lib/mcp/tools/session.js +29 -0
  96. package/lib/mcp/tools/verification/build.d.ts +12 -0
  97. package/lib/mcp/tools/verification/build.js +14 -0
  98. package/lib/mcp/tools/verification/diagnose.d.ts +11 -0
  99. package/lib/mcp/tools/verification/diagnose.js +132 -0
  100. package/lib/mcp/tools/verification/index.d.ts +1 -0
  101. package/lib/mcp/tools/verification/index.js +2 -0
  102. package/lib/mcp/tools/verification/result.d.ts +12 -0
  103. package/lib/mcp/tools/verification/result.js +126 -0
  104. package/lib/mcp/verifications/build.d.ts +5 -0
  105. package/lib/mcp/verifications/build.js +14 -0
  106. package/lib/mcp/verifications/create.d.ts +3 -0
  107. package/lib/mcp/verifications/create.js +57 -0
  108. package/lib/mcp/verifications/find.d.ts +3 -0
  109. package/lib/mcp/verifications/find.js +37 -0
  110. package/lib/mcp/verifications/get.d.ts +3 -0
  111. package/lib/mcp/verifications/get.js +26 -0
  112. package/lib/mcp/verifications/update.d.ts +3 -0
  113. package/lib/mcp/verifications/update.js +78 -0
  114. package/lib/old/client.d.ts +3 -0
  115. package/lib/old/instructions.d.ts +0 -6
  116. package/lib/old/instructions.js +6 -24
  117. package/lib/old/to-register.d.ts +3 -0
  118. package/lib/old/to-register.js +35 -7
  119. package/lib/old/tools/publish.js +13 -1
  120. package/lib/proof/attestor.d.ts +33 -1
  121. package/lib/proof/attestor.js +65 -63
  122. package/lib/proof/index.d.ts +5 -0
  123. package/lib/proof/index.js +6 -0
  124. package/lib/proof/proof-core.d.ts +35 -0
  125. package/lib/proof/proof-core.js +73 -0
  126. package/lib/provider/index.d.ts +5 -0
  127. package/lib/provider/index.js +9 -0
  128. package/lib/provider/to-version.d.ts +9 -12
  129. package/lib/provider/to-version.js +38 -4
  130. package/lib/provider/verification-checks.d.ts +12 -0
  131. package/lib/provider/verification-checks.js +30 -0
  132. package/lib/routes.gen.d.ts +271 -0
  133. package/lib/routes.gen.js +73 -0
  134. package/lib/types/openapi.gen.d.ts +3967 -0
  135. package/lib/types/openapi.gen.js +5 -0
  136. package/package.json +16 -7
  137. package/skill/SKILL.md +35 -14
  138. package/skill/builder-mode.md +9 -0
  139. package/skill/old-mode.md +13 -0
  140. package/src/cdp/capture-engine.ts +256 -0
  141. package/src/cdp/capture.ts +25 -185
  142. package/src/cdp/index.ts +6 -0
  143. package/src/config/store.ts +7 -6
  144. package/src/index.ts +2 -4
  145. package/src/mcp/api/operations.gen.ts +1023 -121
  146. package/src/mcp/api/to-zod.ts +115 -0
  147. package/src/mcp/api/tools.ts +9 -3
  148. package/src/mcp/instructions.ts +15 -0
  149. package/src/mcp/server.ts +5 -4
  150. package/src/mcp/start.ts +14 -4
  151. package/src/mcp/tools/agent/build.ts +2 -18
  152. package/src/mcp/tools/agent/index.ts +4 -0
  153. package/src/mcp/tools/agent/proof.ts +1 -7
  154. package/src/mcp/tools/agent/propose.ts +13 -2
  155. package/src/mcp/tools/agent/publish.ts +10 -2
  156. package/src/mcp/tools/agent/replay.ts +0 -5
  157. package/src/mcp/tools/{credentials → authenticate}/authenticate.ts +9 -8
  158. package/src/mcp/tools/authenticate/build.ts +32 -0
  159. package/src/mcp/tools/authenticate/decrypt-key.ts +64 -0
  160. package/src/mcp/tools/authenticate/eth-key.ts +182 -0
  161. package/src/mcp/tools/authenticate/import.ts +73 -0
  162. package/src/mcp/tools/authenticate/index.ts +4 -0
  163. package/src/mcp/tools/authenticate/issue.ts +50 -0
  164. package/src/mcp/tools/authenticate/resolve-owner-key.ts +60 -0
  165. package/src/mcp/tools/index.ts +6 -0
  166. package/src/mcp/tools/verification/build.ts +16 -0
  167. package/src/mcp/tools/verification/index.ts +2 -0
  168. package/src/mcp/tools/verification/result.ts +155 -0
  169. package/src/old/client.ts +3 -0
  170. package/src/old/instructions.ts +10 -25
  171. package/src/old/to-register.ts +62 -27
  172. package/src/old/tools/publish.ts +17 -1
  173. package/src/proof/attestor.ts +112 -71
  174. package/src/proof/index.ts +21 -0
  175. package/src/proof/proof-core.ts +109 -0
  176. package/src/provider/index.ts +20 -0
  177. package/src/provider/to-version.ts +52 -11
  178. package/src/provider/verification-checks.ts +36 -0
  179. package/lib/mcp/tools/credentials/build.d.ts +0 -16
  180. package/lib/mcp/tools/credentials/build.js +0 -33
  181. package/lib/mcp/tools/credentials/status.js +0 -62
  182. package/src/mcp/tools/credentials/build.ts +0 -37
  183. package/src/mcp/tools/credentials/cache.ts +0 -161
  184. package/src/mcp/tools/credentials/env-file.ts +0 -101
  185. package/src/mcp/tools/credentials/import.ts +0 -72
  186. package/src/mcp/tools/credentials/issue.ts +0 -107
  187. package/src/mcp/tools/credentials/list-cached.ts +0 -66
  188. package/src/mcp/tools/credentials/register.ts +0 -49
  189. package/src/mcp/tools/credentials/resolve-owner-key.ts +0 -78
  190. package/src/mcp/tools/credentials/status.ts +0 -82
  191. package/src/types/openapi.ts +0 -7
  192. /package/lib/mcp/{tools/credentials → credentials}/env-file.d.ts +0 -0
  193. /package/lib/mcp/{tools/credentials → credentials}/env-file.js +0 -0
  194. /package/lib/mcp/{tools/credentials → credentials}/register.d.ts +0 -0
  195. /package/lib/mcp/{tools/credentials → credentials}/register.js +0 -0
  196. /package/lib/mcp/tools/{credentials → authenticate}/authenticate.d.ts +0 -0
  197. /package/lib/mcp/tools/{credentials → authenticate}/import.d.ts +0 -0
  198. /package/lib/mcp/tools/{credentials → authenticate}/issue.d.ts +0 -0
  199. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.d.ts +0 -0
  200. /package/lib/mcp/tools/{credentials → authenticate}/session-cache.js +0 -0
  201. /package/src/mcp/tools/{credentials → authenticate}/session-cache.ts +0 -0
@@ -5,8 +5,10 @@
5
5
  // responseMatches are the regex/contains checks the attestor runs on the
6
6
  // revealed slice; jsonPath/xPath live on responseRedactions (what the prover
7
7
  // reveals), never on responseMatches.
8
+ import { bytesToHex } from '@noble/hashes/utils.js';
8
9
  import { createClaimOnAttestor, } from '@reclaimprotocol/attestor-core';
9
- import { resolveOwnerPrivateKey } from "../mcp/tools/credentials/cache.js";
10
+ import { resolveEthKey } from "../mcp/tools/authenticate/eth-key.js";
11
+ import { buildHttpParams, ensureAttestorCrypto, parseClaim, resolveAttestorUrl, } from "./proof-core.js";
10
12
  import { ensureZkFiles } from "./zk-files.js";
11
13
  /** Trim a captured log stream to the last N entries — for shrinking the
12
14
  * LLM-visible response while the full stream stays in the on-disk dump. */
@@ -80,50 +82,55 @@ function makeCaptureLogger() {
80
82
  };
81
83
  return { logger: make({}), entries };
82
84
  }
83
- /** Default public attestor websocket URL. Resolved per-call so an env-var
84
- * change or per-request override takes effect without restarting the
85
- * MCP server. */
86
- const FALLBACK_ATTESTOR_URL = 'wss://attestor.reclaimprotocol.org:444/ws';
87
- function resolveAttestorUrl(override) {
88
- return (override ?? process.env['RECLAIM_ATTESTOR_URL'] ?? FALLBACK_ATTESTOR_URL);
89
- }
90
85
  // ---------------------------------------------------------------------------
91
86
  // Main entry point
92
87
  // ---------------------------------------------------------------------------
93
- export async function runAttestorProof(provider, secrets, attestorUrl, ownerAddress) {
94
- // The owner is chosen up front (resolve_owner_key) and passed as
95
- // `ownerAddress`; here we just fetch its private key and sign.
96
- const ownerPrivateKey = ownerAddress
97
- ? resolveOwnerPrivateKey(ownerAddress)
98
- : undefined;
99
- if (!ownerPrivateKey) {
100
- return {
101
- proof: undefined,
102
- extractedValue: '',
103
- extractedParameters: {},
104
- verified: false,
105
- error: `No private key available for ownerAddress "${ownerAddress ?? ''}". ` +
106
- 'Call resolve_owner_key to pick a credential (or ' +
107
- 'issue_credentials / import_credentials to set one up), then ' +
108
- 'retry run_proof with its address as ownerAddress.',
109
- errorKind: 'missing-owner-key',
110
- };
88
+ export async function runAttestorProof(provider, secrets, opts = {}) {
89
+ // Sign with the caller-supplied key (the app/VC's ephemeral per-session
90
+ // key) when given; otherwise resolve env/.env/file. `ownerAddress` is a
91
+ // sanity check on the resolved key (ignored when a key is supplied).
92
+ let ownerPrivateKey;
93
+ if (opts.ownerPrivateKey) {
94
+ ownerPrivateKey = opts.ownerPrivateKey;
95
+ }
96
+ else {
97
+ const resolved = resolveEthKey();
98
+ if (!resolved) {
99
+ return {
100
+ proof: undefined,
101
+ extractedValue: '',
102
+ extractedParameters: {},
103
+ verified: false,
104
+ error: 'No eth proof-owner key available (no RECLAIM_PRIVATE_KEY in env, ' +
105
+ '.env, or RECLAIM_PRIVATE_KEY_FILE). Call resolve_owner_key, then ' +
106
+ 'issue_credentials (generate) or import_credentials (provide one), ' +
107
+ 'and retry run_proof.',
108
+ errorKind: 'missing-owner-key',
109
+ };
110
+ }
111
+ if (opts.ownerAddress
112
+ && opts.ownerAddress.toLowerCase() !== resolved.address) {
113
+ return {
114
+ proof: undefined,
115
+ extractedValue: '',
116
+ extractedParameters: {},
117
+ verified: false,
118
+ error: `Requested ownerAddress "${opts.ownerAddress}" does not match ` +
119
+ `the resolved eth key (${resolved.address}, source: ` +
120
+ `${resolved.source}). ` +
121
+ 'Call resolve_owner_key to get the current address, or update the ' +
122
+ 'configured key.',
123
+ errorKind: 'missing-owner-key',
124
+ };
125
+ }
126
+ ownerPrivateKey = resolved.privateKey;
111
127
  }
112
128
  try {
113
- // Circuits aren't downloaded at install time (that blocked the MCP
114
- // server's first launch). Fetch them lazily on the first proof.
129
+ // Init the TLS crypto backend (idempotent), then fetch ZK circuits
130
+ // lazily on the first proof (not at install time).
131
+ ensureAttestorCrypto();
115
132
  await ensureZkFiles();
116
- const params = {
117
- url: provider.url,
118
- method: provider.method,
119
- ...(provider.headers !== undefined && { headers: provider.headers }),
120
- ...(provider.body !== undefined && { body: provider.body }),
121
- responseMatches: provider.responseMatches,
122
- responseRedactions: provider.responseRedactions ?? [],
123
- ...(provider.paramValues !== undefined && {
124
- paramValues: provider.paramValues,
125
- }),
126
- };
133
+ const params = buildHttpParams(provider);
127
134
  // Diagnostic logger capture is gated behind RECLAIM_AGENT_TRACE so the
128
135
  // happy path doesn't pay the cost (the attestor SDK emits a *lot* of
129
136
  // trace/debug entries during ZK setup). Flip RECLAIM_AGENT_TRACE=1 to
@@ -141,8 +148,8 @@ export async function runAttestorProof(provider, secrets, attestorUrl, ownerAddr
141
148
  headers: secrets,
142
149
  },
143
150
  ownerPrivateKey,
144
- client: { url: resolveAttestorUrl(attestorUrl) },
145
- zkEngine: 'snarkjs',
151
+ client: { url: resolveAttestorUrl(opts.attestorUrl) },
152
+ zkEngine: opts.zkEngine ?? 'gnark',
146
153
  ...(capture !== undefined && { logger: capture.logger }),
147
154
  });
148
155
  }
@@ -160,38 +167,33 @@ export async function runAttestorProof(provider, secrets, attestorUrl, ownerAddr
160
167
  }
161
168
  return errorResult;
162
169
  }
163
- // ClaimTunnelResponse carries the claim under `.claim`.
164
- const claimRecord = claim;
165
- const claimData = claimRecord['claim'];
166
- // claimData.context is a JSON-encoded string carrying
167
- // { extractedParameters: {...}, providerHash, ... }.
168
- let context = {};
169
- const rawContext = claimData?.['context'];
170
- if (typeof rawContext === 'string') {
171
- try {
172
- context = JSON.parse(rawContext);
173
- }
174
- catch {
175
- // Leave context empty if it isn't valid JSON.
176
- }
177
- }
178
- const extractedParameters = context['extractedParameters'] ??
179
- {};
180
- const extractedValue = Object.values(extractedParameters)[0] ?? '';
170
+ const { extractedValue, extractedParameters, identifier, owner, claimData } = parseClaim(claim);
181
171
  const result = {
182
172
  proof: claim,
183
173
  extractedValue,
184
174
  extractedParameters,
185
175
  verified: true,
186
176
  };
187
- const identifier = claimData?.['identifier'];
188
- if (typeof identifier === 'string') {
177
+ if (identifier !== undefined) {
189
178
  result.identifier = identifier;
190
179
  }
191
- const owner = claimData?.['owner'];
192
- if (typeof owner === 'string') {
180
+ if (owner !== undefined) {
193
181
  result.owner = owner;
194
182
  }
183
+ // Structured claim + signature so the result JWS can carry a nested,
184
+ // attestor-signed proof the Consumer verifies independently.
185
+ if (opts.includeAttestorClaim) {
186
+ const sigs = claim.signatures;
187
+ if (claimData
188
+ && typeof sigs?.attestorAddress === 'string'
189
+ && sigs.claimSignature instanceof Uint8Array) {
190
+ result.attestorClaim = {
191
+ claim: claimData,
192
+ attestorAddress: sigs.attestorAddress,
193
+ claimSignature: '0x' + bytesToHex(sigs.claimSignature),
194
+ };
195
+ }
196
+ }
195
197
  // Only set when RECLAIM_AGENT_TRACE=1. Full stream — the MCP layer
196
198
  // trims for the LLM-visible response; the on-disk dump gets it all.
197
199
  if (attestorLogs !== undefined && attestorLogs.length > 0) {
@@ -0,0 +1,5 @@
1
+ export type { AttestorClaim, AttestorLogEntry, ProofResult, RunAttestorProofOptions, } from './attestor.ts';
2
+ export { runAttestorProof, tailLogs, warnsAndErrors } from './attestor.ts';
3
+ export { buildHttpParams, ensureAttestorCrypto, type ParsedClaim, parseClaim, resolveAttestorUrl, } from './proof-core.ts';
4
+ export { ensureZkFiles } from './zk-files.ts';
5
+ export { createClaimOnAttestor } from '@reclaimprotocol/attestor-core';
@@ -0,0 +1,6 @@
1
+ export { runAttestorProof, tailLogs, warnsAndErrors } from "./attestor.js";
2
+ export { buildHttpParams, ensureAttestorCrypto, parseClaim, resolveAttestorUrl, } from "./proof-core.js";
3
+ export { ensureZkFiles } from "./zk-files.js";
4
+ // Re-exported attestor-core claim primitive so the agent is the single
5
+ // integration point with @reclaimprotocol/attestor-core across the builder.
6
+ export { createClaimOnAttestor } from '@reclaimprotocol/attestor-core';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Shared attestor-claim plumbing used by both proof callers: the agent's MCP
3
+ * `run_proof` (which resolves the owner key from the credential cache and
4
+ * captures trace logs) and the app's verification runner (which signs with an
5
+ * ephemeral per-session key and builds a nested-proof claim). Only those
6
+ * concerns differ — building the HTTP params, resolving the attestor URL, and
7
+ * parsing the claim response are identical, so they live here.
8
+ */
9
+ import type { ProviderParams } from '@reclaimprotocol/attestor-core';
10
+ import type { ReclaimProvider } from '../provider/schema.ts';
11
+ /** One-time crypto backend init for `@reclaimprotocol/tls` (idempotent). The
12
+ * package ships with an empty `crypto = {}` and defers the backend to the
13
+ * caller; without this the first proof dies inside the TLS client with
14
+ * `crypto.randomBytes is not a function`. Shared by every attestor caller —
15
+ * the agent MCP `run_proof` tool and the app's verification runner. */
16
+ export declare function ensureAttestorCrypto(): void;
17
+ /** Resolve the attestor websocket URL: explicit override → env → public
18
+ * default. Resolved per-call so an env change or per-request override takes
19
+ * effect without restarting. */
20
+ export declare function resolveAttestorUrl(override?: string): string;
21
+ /** Map a verification's provider recipe straight to the attestor's HTTP
22
+ * params — never synthesized from captured traffic. */
23
+ export declare function buildHttpParams(provider: ReclaimProvider): ProviderParams<'http'>;
24
+ export interface ParsedClaim {
25
+ /** ProviderClaimData: provider, parameters, context, owner, identifier, … */
26
+ claimData?: Record<string, unknown>;
27
+ extractedParameters: Record<string, string>;
28
+ extractedValue: string;
29
+ identifier?: string;
30
+ owner?: string;
31
+ }
32
+ /** Pull claimData + decoded `context.extractedParameters` (plus identifier /
33
+ * owner) out of a `createClaimOnAttestor` result. The full result still
34
+ * carries signatures the caller may need for nested-proof building. */
35
+ export declare function parseClaim(claim: unknown): ParsedClaim;
@@ -0,0 +1,73 @@
1
+ import { setCryptoImplementation } from '@reclaimprotocol/tls';
2
+ import { webcryptoCrypto } from '@reclaimprotocol/tls/webcrypto';
3
+ const FALLBACK_ATTESTOR_URL = 'wss://attestor.reclaimprotocol.org:444/ws';
4
+ let cryptoInitialized = false;
5
+ /** One-time crypto backend init for `@reclaimprotocol/tls` (idempotent). The
6
+ * package ships with an empty `crypto = {}` and defers the backend to the
7
+ * caller; without this the first proof dies inside the TLS client with
8
+ * `crypto.randomBytes is not a function`. Shared by every attestor caller —
9
+ * the agent MCP `run_proof` tool and the app's verification runner. */
10
+ export function ensureAttestorCrypto() {
11
+ if (cryptoInitialized) {
12
+ return;
13
+ }
14
+ setCryptoImplementation(webcryptoCrypto);
15
+ cryptoInitialized = true;
16
+ }
17
+ /** Resolve the attestor websocket URL: explicit override → env → public
18
+ * default. Resolved per-call so an env change or per-request override takes
19
+ * effect without restarting. */
20
+ export function resolveAttestorUrl(override) {
21
+ return (override ?? process.env['RECLAIM_ATTESTOR_URL'] ?? FALLBACK_ATTESTOR_URL);
22
+ }
23
+ /** Map a verification's provider recipe straight to the attestor's HTTP
24
+ * params — never synthesized from captured traffic. */
25
+ export function buildHttpParams(provider) {
26
+ return {
27
+ url: provider.url,
28
+ method: provider.method,
29
+ ...(provider.headers !== undefined && { headers: provider.headers }),
30
+ ...(provider.body !== undefined && { body: provider.body }),
31
+ responseMatches: provider.responseMatches,
32
+ responseRedactions: provider.responseRedactions ?? [],
33
+ ...(provider.paramValues !== undefined && {
34
+ paramValues: provider.paramValues,
35
+ }),
36
+ };
37
+ }
38
+ /** Pull claimData + decoded `context.extractedParameters` (plus identifier /
39
+ * owner) out of a `createClaimOnAttestor` result. The full result still
40
+ * carries signatures the caller may need for nested-proof building. */
41
+ export function parseClaim(claim) {
42
+ const claimRecord = claim;
43
+ const claimData = claimRecord['claim'];
44
+ // claimData.context is a JSON-encoded string carrying
45
+ // { extractedParameters: {...}, providerHash, ... }.
46
+ let context = {};
47
+ const rawContext = claimData?.['context'];
48
+ if (typeof rawContext === 'string') {
49
+ try {
50
+ context = JSON.parse(rawContext);
51
+ }
52
+ catch {
53
+ // Leave context empty if it isn't valid JSON.
54
+ }
55
+ }
56
+ const extractedParameters = context['extractedParameters'] ?? {};
57
+ const parsed = {
58
+ extractedParameters,
59
+ extractedValue: Object.values(extractedParameters)[0] ?? '',
60
+ };
61
+ if (claimData) {
62
+ parsed.claimData = claimData;
63
+ }
64
+ const identifier = claimData?.['identifier'];
65
+ if (typeof identifier === 'string') {
66
+ parsed.identifier = identifier;
67
+ }
68
+ const owner = claimData?.['owner'];
69
+ if (typeof owner === 'string') {
70
+ parsed.owner = owner;
71
+ }
72
+ return parsed;
73
+ }
@@ -0,0 +1,5 @@
1
+ export { extractGraphqlOp, looksLikeGraphqlEndpoint } from './graphql.ts';
2
+ export type { CapturedRequest, HttpMethod, OprfMode, ReclaimProvider, RequestConcern, ResponseMatch, ResponseRedaction, SecretParamRef, } from './schema.ts';
3
+ export { classifyHeader, splitSecrets } from './secrets.ts';
4
+ export { hashProviderParams, providers } from '@reclaimprotocol/attestor-core';
5
+ export type { ProviderParams } from '@reclaimprotocol/attestor-core';
@@ -0,0 +1,9 @@
1
+ // Provider primitives shared with the app's capture pipeline:
2
+ // the attestor-derived recipe types, secret classification, and the GraphQL
3
+ // op parser. Exposed as `@reclaimprotocol/agent/provider`.
4
+ export { extractGraphqlOp, looksLikeGraphqlEndpoint } from "./graphql.js";
5
+ export { classifyHeader, splitSecrets } from "./secrets.js";
6
+ // Re-exported attestor-core provider primitives (the registry, the param hash,
7
+ // and the param type) so the builder imports them via the agent rather than
8
+ // depending on @reclaimprotocol/attestor-core directly.
9
+ export { hashProviderParams, providers } from '@reclaimprotocol/attestor-core';
@@ -1,22 +1,19 @@
1
1
  import type { ReclaimClient } from '@reclaimprotocol/client';
2
- import type { CreateProviderVersionRequest as CreateVersionBody, ProviderVersionRef as VersionRef } from '../types/openapi.ts';
2
+ import type { CreateProviderVersionRequest, ProviderVersionRef } from '@reclaimprotocol/client/openapi';
3
3
  import type { ReclaimProvider } from './schema.ts';
4
4
  /**
5
- * Translate a drafted ReclaimProvider into the body for
6
- * POST /providers/{providerId}/versions.
7
- *
8
- * `initialUrl` is the landing page the user navigated to during
9
- * capture — distinct from `provider.url` which is the specific
10
- * API URL the attestor replays.
11
- *
12
- * Secrets are NOT persisted — the verification client re-supplies
13
- * them at runtime via `credentials: 'include'`.
5
+ * Derive the version's `requiredContext` JSON Schema from the
6
+ * `{{context.<name>}}` placeholders in the provider's url/body — mechanical,
7
+ * so a published recipe can never reference a context value the Builder
8
+ * doesn't require. Returns undefined when the recipe has none (the field is
9
+ * optional). Authors can refine types/descriptions in the version editor.
14
10
  */
15
- export declare function providerToCreateVersionRequest(provider: ReclaimProvider, initialUrl: string, notes?: string, version?: VersionRef): CreateVersionBody;
11
+ export declare function deriveRequiredContext(provider: ReclaimProvider): CreateProviderVersionRequest['requiredContext'];
12
+ export declare function providerToCreateVersionRequest(provider: ReclaimProvider, initialUrl: string, notes?: string, version?: ProviderVersionRef): CreateProviderVersionRequest;
16
13
  /**
17
14
  * Fetch the current versions for a provider and return the next version above
18
15
  * the highest existing one (bumping the patch number), or 1.0.0 when the
19
16
  * provider has no versions yet. A failed lookup propagates — silently
20
17
  * resetting to 1.0.0 would re-publish a v3 provider as v1.0.0.
21
18
  */
22
- export declare function nextVersion(client: ReclaimClient, providerId: string): Promise<VersionRef>;
19
+ export declare function nextVersion(client: ReclaimClient, providerId: string): Promise<ProviderVersionRef>;
@@ -9,7 +9,35 @@
9
9
  * Secrets are NOT persisted — the verification client re-supplies
10
10
  * them at runtime via `credentials: 'include'`.
11
11
  */
12
+ /** `{{context.<name>}}` placeholders in a request URL/body: values the
13
+ * CONSUMER supplies at verification time via the session `context`. Bare
14
+ * `{{name}}` placeholders (extraction params) are not consumer-supplied
15
+ * and are ignored. */
16
+ const CONTEXT_PARAM_RE = /\{\{context\.([A-Za-z_][A-Za-z0-9_]*)\}\}/g;
17
+ /**
18
+ * Derive the version's `requiredContext` JSON Schema from the
19
+ * `{{context.<name>}}` placeholders in the provider's url/body — mechanical,
20
+ * so a published recipe can never reference a context value the Builder
21
+ * doesn't require. Returns undefined when the recipe has none (the field is
22
+ * optional). Authors can refine types/descriptions in the version editor.
23
+ */
24
+ export function deriveRequiredContext(provider) {
25
+ const haystack = `${provider.url}\n${provider.body ?? ''}`;
26
+ const names = new Set();
27
+ for (const m of haystack.matchAll(CONTEXT_PARAM_RE)) {
28
+ names.add(m[1]);
29
+ }
30
+ if (!names.size) {
31
+ return undefined;
32
+ }
33
+ const properties = {};
34
+ for (const name of names) {
35
+ properties[name] = { type: 'string' };
36
+ }
37
+ return { type: 'object', required: [...names], properties };
38
+ }
12
39
  export function providerToCreateVersionRequest(provider, initialUrl, notes, version) {
40
+ const requiredContext = deriveRequiredContext(provider);
13
41
  // Inline responseRedactions into matches[*].extract (1-to-1 by index).
14
42
  const matches = (provider.responseMatches ?? []).map((match, i) => {
15
43
  const redaction = provider.responseRedactions?.[i];
@@ -33,10 +61,16 @@ export function providerToCreateVersionRequest(provider, initialUrl, notes, vers
33
61
  },
34
62
  ],
35
63
  allowedJsRequests: [],
36
- webSettings: { geoLocation: '{{DYNAMIC_GEO}}' },
37
- ...(provider.paramValues
38
- ? { requiredParameters: provider.paramValues }
39
- : {}),
64
+ // Mirror the builder openapi defaults explicitly — the server does not
65
+ // apply schema defaults to request bodies.
66
+ webSettings: {
67
+ geoLocation: '{{DYNAMIC_GEO}}',
68
+ clientOptions: { portal: { useProxy: true } },
69
+ },
70
+ // Derived from `{{context.<name>}}` placeholders only — a captured
71
+ // provider's `paramValues` are extracted response parameters, not
72
+ // consumer context, and never become requiredContext.
73
+ ...(requiredContext ? { requiredContext } : {}),
40
74
  ...(notes ? { notes } : {}),
41
75
  };
42
76
  }
@@ -0,0 +1,12 @@
1
+ import type { ReclaimProvider } from './schema.ts';
2
+ /**
3
+ * Advisory pre-publish lint for a drafted provider — never a gate. Surfaces
4
+ * only what the AUTHOR must decide; everything testable is tested by the
5
+ * verification client itself (CDP capture sees all traffic — navigations,
6
+ * XHRs, fetches — and `checkCandidate` in packages/app src/verify/run.ts
7
+ * selects the captured request that satisfies the recipe, skipping the
8
+ * rest). Interpolation and matching are plain text and work for any
9
+ * captured content; extract selectors apply client-side in spec order
10
+ * xPath → jsonPath → regex, each to the prior selection.
11
+ */
12
+ export declare function verificationWarnings(provider: ReclaimProvider): string[];
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Advisory pre-publish lint for a drafted provider — never a gate. Surfaces
3
+ * only what the AUTHOR must decide; everything testable is tested by the
4
+ * verification client itself (CDP capture sees all traffic — navigations,
5
+ * XHRs, fetches — and `checkCandidate` in packages/app src/verify/run.ts
6
+ * selects the captured request that satisfies the recipe, skipping the
7
+ * rest). Interpolation and matching are plain text and work for any
8
+ * captured content; extract selectors apply client-side in spec order
9
+ * xPath → jsonPath → regex, each to the prior selection.
10
+ */
11
+ export function verificationWarnings(provider) {
12
+ const out = [];
13
+ // Untemplated user-specific URL parts: any captured param value baked
14
+ // literally into the URL makes the provider user-specific. Only the dev
15
+ // can decide: consumer-supplied → {{context.<name>}} (declared in
16
+ // requiredContext; consumers then send the exact value and the VC matches
17
+ // only that value), bare {{<name>}} (resolved from the end-user's own
18
+ // traffic), or re-capture a non-user-specific endpoint.
19
+ for (const [name, value] of Object.entries(provider.paramValues ?? {})) {
20
+ if (value.length >= 3 && provider.url.includes(value)) {
21
+ out.push(`The URL contains the captured value "${value}" (param ` +
22
+ `"${name}") as a literal. Decide with the dev: if consumers ` +
23
+ 'supply it, replace with {{context.' + name + '}} (published ' +
24
+ 'requiredContext will require it; verification matches only ' +
25
+ 'the supplied value). Leaving it literal pins the provider ' +
26
+ 'to this user.');
27
+ }
28
+ }
29
+ return out;
30
+ }