@probemesh/sdk 0.1.0

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 (83) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +160 -0
  3. package/dist/chunk-257Y7LN2.js +827 -0
  4. package/dist/chunk-257Y7LN2.js.map +1 -0
  5. package/dist/chunk-2ASMVLG4.js +56 -0
  6. package/dist/chunk-2ASMVLG4.js.map +1 -0
  7. package/dist/chunk-2KWGHJYP.js +285 -0
  8. package/dist/chunk-2KWGHJYP.js.map +1 -0
  9. package/dist/chunk-3H7UGVI6.js +1117 -0
  10. package/dist/chunk-3H7UGVI6.js.map +1 -0
  11. package/dist/chunk-5Q3PDYIA.js +657 -0
  12. package/dist/chunk-5Q3PDYIA.js.map +1 -0
  13. package/dist/chunk-CXZOO3U4.js +550 -0
  14. package/dist/chunk-CXZOO3U4.js.map +1 -0
  15. package/dist/chunk-FRFBK4SY.js +270 -0
  16. package/dist/chunk-FRFBK4SY.js.map +1 -0
  17. package/dist/chunk-HJK52QJF.js +994 -0
  18. package/dist/chunk-HJK52QJF.js.map +1 -0
  19. package/dist/chunk-HNBDX7IU.js +705 -0
  20. package/dist/chunk-HNBDX7IU.js.map +1 -0
  21. package/dist/chunk-NYTV263W.js +116 -0
  22. package/dist/chunk-NYTV263W.js.map +1 -0
  23. package/dist/chunk-PXG54XOG.js +595 -0
  24. package/dist/chunk-PXG54XOG.js.map +1 -0
  25. package/dist/chunk-TDOBAMYM.js +607 -0
  26. package/dist/chunk-TDOBAMYM.js.map +1 -0
  27. package/dist/chunk-TV42EZSI.js +2157 -0
  28. package/dist/chunk-TV42EZSI.js.map +1 -0
  29. package/dist/chunk-UU2ZG7P7.js +408 -0
  30. package/dist/chunk-UU2ZG7P7.js.map +1 -0
  31. package/dist/chunk-WKN7QOCA.js +977 -0
  32. package/dist/chunk-WKN7QOCA.js.map +1 -0
  33. package/dist/chunk-ZJOLPBJJ.js +1091 -0
  34. package/dist/chunk-ZJOLPBJJ.js.map +1 -0
  35. package/dist/cli/audit-trail-export.cjs +1193 -0
  36. package/dist/cli/audit-trail-export.cjs.map +1 -0
  37. package/dist/cli/audit-trail-export.d.cts +1 -0
  38. package/dist/cli/audit-trail-export.d.ts +1 -0
  39. package/dist/cli/audit-trail-export.js +24 -0
  40. package/dist/cli/audit-trail-export.js.map +1 -0
  41. package/dist/cli/catalog-check.cjs +2687 -0
  42. package/dist/cli/catalog-check.cjs.map +1 -0
  43. package/dist/cli/catalog-check.d.cts +1 -0
  44. package/dist/cli/catalog-check.d.ts +1 -0
  45. package/dist/cli/catalog-check.js +26 -0
  46. package/dist/cli/catalog-check.js.map +1 -0
  47. package/dist/cli/probemesh-init.cjs +1049 -0
  48. package/dist/cli/probemesh-init.cjs.map +1 -0
  49. package/dist/cli/probemesh-init.d.cts +1 -0
  50. package/dist/cli/probemesh-init.d.ts +1 -0
  51. package/dist/cli/probemesh-init.js +22 -0
  52. package/dist/cli/probemesh-init.js.map +1 -0
  53. package/dist/cli/provider-conformance.cjs +6180 -0
  54. package/dist/cli/provider-conformance.cjs.map +1 -0
  55. package/dist/cli/provider-conformance.d.cts +1 -0
  56. package/dist/cli/provider-conformance.d.ts +1 -0
  57. package/dist/cli/provider-conformance.js +29 -0
  58. package/dist/cli/provider-conformance.js.map +1 -0
  59. package/dist/cli/provider-dossier-check.cjs +2978 -0
  60. package/dist/cli/provider-dossier-check.cjs.map +1 -0
  61. package/dist/cli/provider-dossier-check.d.cts +1 -0
  62. package/dist/cli/provider-dossier-check.d.ts +1 -0
  63. package/dist/cli/provider-dossier-check.js +27 -0
  64. package/dist/cli/provider-dossier-check.js.map +1 -0
  65. package/dist/cli/provider-dossier.cjs +1753 -0
  66. package/dist/cli/provider-dossier.cjs.map +1 -0
  67. package/dist/cli/provider-dossier.d.cts +1 -0
  68. package/dist/cli/provider-dossier.d.ts +1 -0
  69. package/dist/cli/provider-dossier.js +26 -0
  70. package/dist/cli/provider-dossier.js.map +1 -0
  71. package/dist/cli/x402-accept.cjs +6009 -0
  72. package/dist/cli/x402-accept.cjs.map +1 -0
  73. package/dist/cli/x402-accept.d.cts +1 -0
  74. package/dist/cli/x402-accept.d.ts +1 -0
  75. package/dist/cli/x402-accept.js +28 -0
  76. package/dist/cli/x402-accept.js.map +1 -0
  77. package/dist/index.cjs +13671 -0
  78. package/dist/index.cjs.map +1 -0
  79. package/dist/index.d.cts +2026 -0
  80. package/dist/index.d.ts +2026 -0
  81. package/dist/index.js +2560 -0
  82. package/dist/index.js.map +1 -0
  83. package/package.json +111 -0
@@ -0,0 +1,827 @@
1
+ import {
2
+ createProbeMesh,
3
+ startHostedRouter
4
+ } from "./chunk-TV42EZSI.js";
5
+ import {
6
+ createProviderCatalogArtifact,
7
+ formatProviderCatalogArtifact
8
+ } from "./chunk-3H7UGVI6.js";
9
+ import {
10
+ loadCliConfigDefault,
11
+ redactX402Secrets
12
+ } from "./chunk-NYTV263W.js";
13
+ import {
14
+ ProbeMeshError,
15
+ isProbeMeshError
16
+ } from "./chunk-2ASMVLG4.js";
17
+
18
+ // src/protocols/x402Acceptance.ts
19
+ var DEFAULT_REQUIRED_RECEIPT_TYPES = [
20
+ "payment_proof",
21
+ "settlement_confirmation",
22
+ "provider_delivery"
23
+ ];
24
+ async function runX402ProviderAcceptance(options) {
25
+ assertAcceptanceOptions(options);
26
+ const telemetryEvents = [];
27
+ const requiredReceiptTypes = options.requiredReceiptTypes ?? DEFAULT_REQUIRED_RECEIPT_TYPES;
28
+ const hostedRouter = await startHostedRouter({
29
+ port: 0,
30
+ adapters: options.adapters,
31
+ apiKeys: options.apiKey ? [options.apiKey] : void 0,
32
+ onTelemetryEvent(event) {
33
+ telemetryEvents.push(event);
34
+ }
35
+ });
36
+ let response;
37
+ let error;
38
+ try {
39
+ const probemesh = createProbeMesh({
40
+ hosted: {
41
+ baseUrl: hostedRouter.url,
42
+ apiKey: options.apiKey
43
+ }
44
+ });
45
+ try {
46
+ response = await probemesh.call(options.request);
47
+ } catch (caught) {
48
+ error = toAcceptanceError(caught);
49
+ }
50
+ } finally {
51
+ await hostedRouter.close();
52
+ }
53
+ const baseChecks = createAcceptanceChecks({
54
+ response,
55
+ error,
56
+ telemetryEvents,
57
+ expectedProviderId: options.expectedProviderId,
58
+ requiredReceiptTypes
59
+ });
60
+ const checks = [
61
+ ...baseChecks,
62
+ createSecretSafeOutputCheck({
63
+ response,
64
+ error,
65
+ telemetryEvents,
66
+ checks: baseChecks,
67
+ requiredReceiptTypes,
68
+ forbiddenOutputValues: options.forbiddenOutputValues ?? []
69
+ })
70
+ ];
71
+ const status = checks.every((check) => check.status === "passed") ? "passed" : "failed";
72
+ const forbiddenOutputValues = options.forbiddenOutputValues ?? [];
73
+ const sanitizedChecks = sanitizeAcceptanceOutput(checks, forbiddenOutputValues);
74
+ const sanitizedResponse = sanitizeAcceptanceOutput(response, forbiddenOutputValues);
75
+ const sanitizedError = sanitizeAcceptanceOutput(error, forbiddenOutputValues);
76
+ const sanitizedTelemetryEvents = sanitizeAcceptanceOutput(
77
+ telemetryEvents,
78
+ forbiddenOutputValues
79
+ );
80
+ return {
81
+ status,
82
+ checks: sanitizedChecks,
83
+ response: sanitizedResponse,
84
+ error: sanitizedError,
85
+ telemetryEvents: sanitizedTelemetryEvents,
86
+ summary: createSummary({
87
+ status,
88
+ checks: sanitizedChecks,
89
+ response: sanitizedResponse,
90
+ error: sanitizedError,
91
+ telemetryEvents: sanitizedTelemetryEvents,
92
+ requiredReceiptTypes
93
+ })
94
+ };
95
+ }
96
+ function summarizeX402AcceptanceResult(result) {
97
+ return createSummary({
98
+ status: result.status,
99
+ checks: result.checks,
100
+ response: result.response,
101
+ error: result.error,
102
+ telemetryEvents: result.telemetryEvents,
103
+ requiredReceiptTypes: result.summary.requiredReceiptTypes
104
+ });
105
+ }
106
+ function evaluateX402ProviderAcceptanceGate(result, options = {}) {
107
+ const requiredCheckNames = options.requiredCheckNames ?? result.checks.map((check) => check.name);
108
+ const failedRequiredCheckNames = requiredCheckNames.filter((checkName) => {
109
+ const check = result.checks.find((candidate) => candidate.name === checkName);
110
+ return check?.status !== "passed";
111
+ });
112
+ const reasons = createGateReasons({
113
+ result,
114
+ requiredCheckNames,
115
+ failedRequiredCheckNames
116
+ });
117
+ const accepted = result.status === "passed" && failedRequiredCheckNames.length === 0;
118
+ return {
119
+ accepted,
120
+ status: accepted ? "accepted" : "rejected",
121
+ requiredCheckNames: [...requiredCheckNames],
122
+ failedRequiredCheckNames,
123
+ reasons: accepted ? ["All required x402 provider acceptance checks passed."] : reasons
124
+ };
125
+ }
126
+ function createX402ProviderAcceptanceReport(result, options = {}) {
127
+ const summary = summarizeX402AcceptanceResult(result);
128
+ const receiptRefs = result.response?.receiptRefs ?? result.error?.receiptRefs;
129
+ const report = {
130
+ title: options.title ?? "x402 Provider Acceptance Report",
131
+ status: result.status,
132
+ gate: evaluateX402ProviderAcceptanceGate(result, options.gate),
133
+ summary,
134
+ checks: result.checks,
135
+ receipts: summarizeAcceptanceReceipts(receiptRefs),
136
+ route: summary.route,
137
+ timelineEventTypes: summary.timelineEventTypes,
138
+ telemetryEventTypes: summary.telemetryEventTypes,
139
+ safety: summary.safety,
140
+ retrySafety: summary.retrySafety,
141
+ error: result.error
142
+ };
143
+ return sanitizeAcceptanceOutput(report, options.forbiddenOutputValues ?? []);
144
+ }
145
+ function formatX402ProviderAcceptanceReport(report, options = {}) {
146
+ const sanitizedReport = sanitizeAcceptanceOutput(report, []);
147
+ if ((options.format ?? "markdown") === "json") {
148
+ return JSON.stringify(sanitizedReport, null, 2);
149
+ }
150
+ return formatAcceptanceReportMarkdown(sanitizedReport);
151
+ }
152
+ function createAcceptanceChecks(options) {
153
+ return [
154
+ completedResponseCheck(options.response, options.error),
155
+ selectedProviderCheck(
156
+ options.response,
157
+ options.error,
158
+ options.expectedProviderId
159
+ ),
160
+ routeMetadataCheck(options.response, options.error),
161
+ timelineEventsCheck(options.response, options.error),
162
+ requiredReceiptsCheck(options.response, options.error, options.requiredReceiptTypes),
163
+ safetySettledDeliveredCheck(options.response, options.error),
164
+ retrySafetyAfterSuccessCheck(options.response, options.error),
165
+ telemetryMatchesTimelineCheck(options.response, options.telemetryEvents)
166
+ ];
167
+ }
168
+ function createGateReasons(options) {
169
+ const reasons = [];
170
+ if (options.result.status !== "passed") {
171
+ reasons.push(`Acceptance result status is "${options.result.status}".`);
172
+ }
173
+ for (const checkName of options.failedRequiredCheckNames) {
174
+ const check = options.result.checks.find(
175
+ (candidate) => candidate.name === checkName
176
+ );
177
+ if (!check) {
178
+ reasons.push(`Required check "${checkName}" was not found.`);
179
+ continue;
180
+ }
181
+ reasons.push(`Required check "${checkName}" failed: ${check.message}`);
182
+ }
183
+ return reasons;
184
+ }
185
+ function summarizeAcceptanceReceipts(receiptRefs) {
186
+ const receipts = receiptRefs ?? [];
187
+ const byType = {};
188
+ for (const receiptRef of receipts) {
189
+ byType[receiptRef.type] = (byType[receiptRef.type] ?? 0) + 1;
190
+ }
191
+ return {
192
+ total: receipts.length,
193
+ types: getReceiptTypes(receipts),
194
+ providers: [
195
+ ...new Set(receipts.map((receiptRef) => receiptRef.provider))
196
+ ],
197
+ byType,
198
+ hasPaymentProof: receipts.some(
199
+ (receiptRef) => receiptRef.type === "payment_proof"
200
+ ),
201
+ hasSettlementConfirmation: receipts.some(
202
+ (receiptRef) => receiptRef.type === "settlement_confirmation"
203
+ ),
204
+ hasProviderDelivery: receipts.some(
205
+ (receiptRef) => receiptRef.type === "provider_delivery"
206
+ )
207
+ };
208
+ }
209
+ function formatAcceptanceReportMarkdown(report) {
210
+ const lines = [
211
+ `# ${report.title}`,
212
+ "",
213
+ `Gate: ${report.gate.status}`,
214
+ `Acceptance: ${report.status}`,
215
+ `Provider: ${report.summary.providerId ?? "unknown"}`,
216
+ `Call: ${report.summary.callId ?? "unknown"}`,
217
+ `Error: ${report.summary.errorCode ?? "none"}`,
218
+ "",
219
+ "## Gate Reasons",
220
+ ...formatList(report.gate.reasons),
221
+ "",
222
+ "## Checks",
223
+ ...report.checks.map(
224
+ (check) => `- [${check.status === "passed" ? "x" : " "}] ${check.name}: ${check.message}`
225
+ ),
226
+ "",
227
+ "## Receipts",
228
+ `- Total: ${report.receipts.total}`,
229
+ `- Types: ${formatInlineList(report.receipts.types)}`,
230
+ `- Providers: ${formatInlineList(report.receipts.providers)}`,
231
+ `- Payment proof: ${String(report.receipts.hasPaymentProof)}`,
232
+ `- Settlement confirmation: ${String(
233
+ report.receipts.hasSettlementConfirmation
234
+ )}`,
235
+ `- Provider delivery: ${String(report.receipts.hasProviderDelivery)}`,
236
+ "",
237
+ "## Route",
238
+ `- Route ID: ${report.route?.routeId ?? "none"}`,
239
+ `- Selected provider: ${report.route?.selectedProviderId ?? "none"}`,
240
+ `- Fallback used: ${String(report.route?.fallbackUsed ?? false)}`,
241
+ `- Stop reason: ${report.route?.stopReason ?? "none"}`,
242
+ "",
243
+ "## Safety",
244
+ `- Payment: ${report.safety?.paymentStatus ?? "unknown"}`,
245
+ `- Settlement: ${report.safety?.settlementStatus ?? "unknown"}`,
246
+ `- Delivery: ${report.safety?.deliveryStatus ?? "unknown"}`,
247
+ `- Money may have moved: ${String(
248
+ report.safety?.moneyMayHaveMoved ?? false
249
+ )}`,
250
+ "",
251
+ "## Retry Safety",
252
+ `- Retryable: ${String(report.retrySafety?.retryable ?? false)}`,
253
+ `- Safe to auto retry: ${String(
254
+ report.retrySafety?.safeToAutoRetry ?? false
255
+ )}`,
256
+ `- Reason: ${report.retrySafety?.reason ?? "unknown"}`,
257
+ "",
258
+ "## Timeline",
259
+ `- Events: ${formatInlineList(report.timelineEventTypes)}`,
260
+ `- Telemetry: ${formatInlineList(report.telemetryEventTypes)}`
261
+ ];
262
+ return `${lines.join("\n")}
263
+ `;
264
+ }
265
+ function formatList(values) {
266
+ if (values.length === 0) {
267
+ return ["- none"];
268
+ }
269
+ return values.map((value) => `- ${value}`);
270
+ }
271
+ function formatInlineList(values) {
272
+ return values.length > 0 ? values.join(", ") : "none";
273
+ }
274
+ function completedResponseCheck(response, error) {
275
+ if (response?.status === "completed") {
276
+ return pass("completed_response", "Hosted x402 call completed.");
277
+ }
278
+ return fail(
279
+ "completed_response",
280
+ error ? `Hosted x402 call failed with ${error.code}.` : "Hosted x402 call did not return a completed response.",
281
+ {
282
+ errorCode: error?.code,
283
+ errorMessage: error?.message
284
+ }
285
+ );
286
+ }
287
+ function selectedProviderCheck(response, error, expectedProviderId) {
288
+ const providerId = response?.provider.id;
289
+ if (providerId && (!expectedProviderId || providerId === expectedProviderId)) {
290
+ return pass("selected_provider", "Hosted route selected the expected provider.", {
291
+ providerId
292
+ });
293
+ }
294
+ return fail("selected_provider", "Hosted route did not select the expected provider.", {
295
+ expectedProviderId,
296
+ providerId,
297
+ errorProvider: error?.provider
298
+ });
299
+ }
300
+ function routeMetadataCheck(response, error) {
301
+ if (response?.route?.mode === "hosted" && typeof response.route.routeId === "string" && response.route.routeId.length > 0) {
302
+ return pass("route_metadata", "Hosted route metadata is present.", {
303
+ routeId: response.route.routeId,
304
+ selectedProviderId: response.route.selectedProviderId
305
+ });
306
+ }
307
+ return fail("route_metadata", "Hosted route metadata is missing.", {
308
+ errorRouteId: error?.route?.routeId
309
+ });
310
+ }
311
+ function timelineEventsCheck(response, error) {
312
+ const timelineEventTypes = response?.timeline?.events.map((event) => event.type) ?? [];
313
+ const requiredEvents = [
314
+ "call.requested",
315
+ "provider.attempted",
316
+ "provider.selected",
317
+ "payment.attempted",
318
+ "receipt.recorded",
319
+ "call.completed"
320
+ ];
321
+ const missingEvents = requiredEvents.filter(
322
+ (eventType) => !timelineEventTypes.includes(eventType)
323
+ );
324
+ if (missingEvents.length === 0) {
325
+ return pass("timeline_events", "Hosted timeline contains the x402 acceptance events.", {
326
+ timelineEventTypes
327
+ });
328
+ }
329
+ return fail("timeline_events", "Hosted timeline is missing required x402 events.", {
330
+ missingEvents,
331
+ timelineEventTypes,
332
+ errorTimelineEventTypes: error?.timeline?.events.map((event) => event.type)
333
+ });
334
+ }
335
+ function requiredReceiptsCheck(response, error, requiredReceiptTypes) {
336
+ const receiptTypes = getReceiptTypes(response?.receiptRefs);
337
+ const missingReceiptTypes = requiredReceiptTypes.filter(
338
+ (receiptType) => !receiptTypes.includes(receiptType)
339
+ );
340
+ if (missingReceiptTypes.length === 0) {
341
+ return pass("required_receipts", "Required x402 receipts are present.", {
342
+ receiptTypes
343
+ });
344
+ }
345
+ return fail("required_receipts", "Required x402 receipts are missing.", {
346
+ missingReceiptTypes,
347
+ receiptTypes,
348
+ errorReceiptTypes: getReceiptTypes(error?.receiptRefs)
349
+ });
350
+ }
351
+ function safetySettledDeliveredCheck(response, error) {
352
+ const safety = response?.safety;
353
+ if (safety?.paymentStatus === "authorized" && safety.settlementStatus === "settled" && safety.deliveryStatus === "delivered" && safety.moneyMayHaveMoved === true) {
354
+ return pass("safety_settled_delivered", "Safety metadata proves authorized, settled delivery.", {
355
+ safety
356
+ });
357
+ }
358
+ return fail(
359
+ "safety_settled_delivered",
360
+ "Safety metadata does not prove settled delivery.",
361
+ {
362
+ safety,
363
+ errorSafety: error?.safety
364
+ }
365
+ );
366
+ }
367
+ function retrySafetyAfterSuccessCheck(response, error) {
368
+ const retrySafety = response?.retrySafety;
369
+ if (retrySafety?.retryable === false && retrySafety.safeToAutoRetry === false && retrySafety.reason === "completed") {
370
+ return pass("retry_safety_after_success", "Completed paid call is not retryable.", {
371
+ retrySafety
372
+ });
373
+ }
374
+ return fail(
375
+ "retry_safety_after_success",
376
+ "Completed paid call retry safety is missing or incorrect.",
377
+ {
378
+ retrySafety,
379
+ errorRetrySafety: error?.retrySafety
380
+ }
381
+ );
382
+ }
383
+ function telemetryMatchesTimelineCheck(response, telemetryEvents) {
384
+ const timelineEventTypes = response?.timeline?.events.map((event) => event.type) ?? [];
385
+ const telemetryEventTypes = telemetryEvents.map((event) => event.type);
386
+ const matches = timelineEventTypes.length > 0 && timelineEventTypes.length === telemetryEventTypes.length && timelineEventTypes.every(
387
+ (eventType, index) => eventType === telemetryEventTypes[index]
388
+ );
389
+ if (matches) {
390
+ return pass("telemetry_matches_timeline", "Telemetry mirrors the hosted timeline.", {
391
+ telemetryEventTypes
392
+ });
393
+ }
394
+ return fail("telemetry_matches_timeline", "Telemetry does not mirror the hosted timeline.", {
395
+ timelineEventTypes,
396
+ telemetryEventTypes
397
+ });
398
+ }
399
+ function createSecretSafeOutputCheck(options) {
400
+ const forbiddenOutputValues = options.forbiddenOutputValues.filter(
401
+ (value) => value.length > 0
402
+ );
403
+ const candidate = {
404
+ response: options.response,
405
+ error: options.error,
406
+ telemetryEvents: options.telemetryEvents,
407
+ checks: options.checks,
408
+ summary: createSummary({
409
+ status: options.checks.every((check) => check.status === "passed") ? "passed" : "failed",
410
+ checks: options.checks,
411
+ response: options.response,
412
+ error: options.error,
413
+ telemetryEvents: options.telemetryEvents,
414
+ requiredReceiptTypes: options.requiredReceiptTypes
415
+ })
416
+ };
417
+ const serialized = JSON.stringify(candidate);
418
+ const leakedValues = forbiddenOutputValues.filter(
419
+ (value) => serialized.includes(value)
420
+ );
421
+ if (leakedValues.length === 0) {
422
+ return pass("secret_safe_output", "Serialized acceptance output contains no forbidden values.", {
423
+ checkedForbiddenValueCount: forbiddenOutputValues.length
424
+ });
425
+ }
426
+ return fail("secret_safe_output", "Serialized acceptance output contains forbidden values.", {
427
+ leakedValueCount: leakedValues.length
428
+ });
429
+ }
430
+ function createSummary(options) {
431
+ const receiptRefs = options.response?.receiptRefs ?? options.error?.receiptRefs;
432
+ const timeline = options.response?.timeline ?? options.error?.timeline;
433
+ const route = options.response?.route ?? options.error?.route;
434
+ const failedCheckNames = options.checks.filter((check) => check.status === "failed").map((check) => check.name);
435
+ return {
436
+ status: options.status,
437
+ totalChecks: options.checks.length,
438
+ passedChecks: options.checks.length - failedCheckNames.length,
439
+ failedChecks: failedCheckNames.length,
440
+ failedCheckNames,
441
+ callId: options.response?.callId ?? options.error?.callId,
442
+ providerId: options.response?.provider.id ?? options.error?.provider,
443
+ errorCode: options.error?.code,
444
+ receiptTypes: getReceiptTypes(receiptRefs),
445
+ requiredReceiptTypes: [...options.requiredReceiptTypes],
446
+ timelineEventTypes: timeline?.events.map((event) => event.type) ?? [],
447
+ telemetryEventTypes: options.telemetryEvents.map((event) => event.type),
448
+ safety: options.response?.safety ?? options.error?.safety,
449
+ retrySafety: options.response?.retrySafety ?? options.error?.retrySafety,
450
+ route: route ? {
451
+ routeId: route.routeId,
452
+ selectedProviderId: route.selectedProviderId,
453
+ fallbackUsed: route.explanation?.fallbackUsed,
454
+ fallbackCount: route.explanation?.fallbackCount,
455
+ stopReason: route.explanation?.stopReason
456
+ } : void 0
457
+ };
458
+ }
459
+ function toAcceptanceError(error) {
460
+ if (isProbeMeshError(error)) {
461
+ return {
462
+ name: "ProbeMeshError",
463
+ code: error.code,
464
+ message: error.message,
465
+ status: "failed",
466
+ capability: error.capability,
467
+ provider: error.provider,
468
+ callId: error.callId,
469
+ receiptRefs: error.receiptRefs,
470
+ safety: error.safety,
471
+ timeline: error.timeline,
472
+ retrySafety: error.retrySafety,
473
+ route: error.route
474
+ };
475
+ }
476
+ return {
477
+ name: "ProbeMeshError",
478
+ code: "provider_unavailable",
479
+ message: error instanceof Error ? error.message : "x402 provider acceptance call failed.",
480
+ status: "failed"
481
+ };
482
+ }
483
+ function getReceiptTypes(receiptRefs) {
484
+ return [...new Set((receiptRefs ?? []).map((receiptRef) => receiptRef.type))];
485
+ }
486
+ function sanitizeAcceptanceOutput(value, forbiddenOutputValues) {
487
+ const forbiddenValues = forbiddenOutputValues.filter((entry) => entry.length > 0);
488
+ return redactX402Secrets(
489
+ replaceForbiddenValues(value, forbiddenValues, /* @__PURE__ */ new WeakSet())
490
+ );
491
+ }
492
+ function replaceForbiddenValues(value, forbiddenValues, seen) {
493
+ if (typeof value === "string") {
494
+ return forbiddenValues.reduce(
495
+ (current, forbidden) => current.split(forbidden).join("[REDACTED]"),
496
+ value
497
+ );
498
+ }
499
+ if (value === null || typeof value !== "object" || value instanceof Date) {
500
+ return value;
501
+ }
502
+ if (seen.has(value)) {
503
+ return "[Circular]";
504
+ }
505
+ seen.add(value);
506
+ if (Array.isArray(value)) {
507
+ const entries2 = value.map(
508
+ (entry) => replaceForbiddenValues(entry, forbiddenValues, seen)
509
+ );
510
+ seen.delete(value);
511
+ return entries2;
512
+ }
513
+ const entries = Object.fromEntries(
514
+ Object.entries(value).map(([key, entry]) => [
515
+ key,
516
+ replaceForbiddenValues(entry, forbiddenValues, seen)
517
+ ])
518
+ );
519
+ seen.delete(value);
520
+ return entries;
521
+ }
522
+ function pass(name, message, details) {
523
+ return {
524
+ name,
525
+ status: "passed",
526
+ message,
527
+ details
528
+ };
529
+ }
530
+ function fail(name, message, details) {
531
+ return {
532
+ name,
533
+ status: "failed",
534
+ message,
535
+ details
536
+ };
537
+ }
538
+ function assertAcceptanceOptions(options) {
539
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
540
+ throw invalidOptions("x402 acceptance options must be an object.");
541
+ }
542
+ if (!Array.isArray(options.adapters) || options.adapters.length === 0) {
543
+ throw invalidOptions("x402 acceptance options require at least one adapter.");
544
+ }
545
+ if (!options.request || typeof options.request !== "object" || Array.isArray(options.request)) {
546
+ throw invalidOptions("x402 acceptance options require a call request object.");
547
+ }
548
+ if (options.apiKey !== void 0 && (typeof options.apiKey !== "string" || options.apiKey.length === 0)) {
549
+ throw invalidOptions("x402 acceptance apiKey must be a non-empty string.");
550
+ }
551
+ if (options.expectedProviderId !== void 0 && (typeof options.expectedProviderId !== "string" || options.expectedProviderId.length === 0)) {
552
+ throw invalidOptions(
553
+ "x402 acceptance expectedProviderId must be a non-empty string."
554
+ );
555
+ }
556
+ if (options.requiredReceiptTypes !== void 0 && (!Array.isArray(options.requiredReceiptTypes) || options.requiredReceiptTypes.some(
557
+ (receiptType) => typeof receiptType !== "string" || receiptType.length === 0
558
+ ))) {
559
+ throw invalidOptions(
560
+ "x402 acceptance requiredReceiptTypes must be an array of receipt type strings."
561
+ );
562
+ }
563
+ if (options.forbiddenOutputValues !== void 0 && (!Array.isArray(options.forbiddenOutputValues) || options.forbiddenOutputValues.some((value) => typeof value !== "string"))) {
564
+ throw invalidOptions(
565
+ "x402 acceptance forbiddenOutputValues must be an array of strings."
566
+ );
567
+ }
568
+ }
569
+ function invalidOptions(message) {
570
+ return new ProbeMeshError({
571
+ code: "invalid_request",
572
+ message
573
+ });
574
+ }
575
+
576
+ // src/cli/x402AcceptanceCli.ts
577
+ import { mkdir, writeFile } from "fs/promises";
578
+ import { dirname, resolve } from "path";
579
+ var USAGE = `Usage: probemesh-x402-accept --config <path> [--format markdown|json] [--out-json <path>] [--out-md <path>] [--out-catalog <path>] [--title <text>]`;
580
+ async function runX402ProviderAcceptanceCli(options = {}) {
581
+ const argv = options.argv ?? [];
582
+ const cwd = options.cwd ?? process.cwd();
583
+ try {
584
+ const parsedArgs = parseCliArgs(argv);
585
+ if (parsedArgs.help) {
586
+ return {
587
+ exitCode: 0,
588
+ skipped: true,
589
+ stdout: `${USAGE}
590
+ `
591
+ };
592
+ }
593
+ if (!parsedArgs.configPath) {
594
+ return cliFailure("--config <path> is required.");
595
+ }
596
+ const configExport = await loadCliConfig(parsedArgs.configPath, {
597
+ argv,
598
+ cwd
599
+ });
600
+ if (isCliSkip(configExport)) {
601
+ return {
602
+ exitCode: 0,
603
+ skipped: true,
604
+ skip: configExport,
605
+ stdout: `x402 acceptance skipped: ${configExport.reason}
606
+ `
607
+ };
608
+ }
609
+ assertCliConfig(configExport);
610
+ const result = await runX402ProviderAcceptance(configExport.acceptance);
611
+ const report = createX402ProviderAcceptanceReport(result, {
612
+ ...configExport.report ?? {},
613
+ title: parsedArgs.title ?? configExport.report?.title,
614
+ forbiddenOutputValues: mergeForbiddenOutputValues(configExport)
615
+ });
616
+ const selectedFormat = parsedArgs.format ?? configExport.report?.format ?? "markdown";
617
+ const stdout = formatX402ProviderAcceptanceReport(report, {
618
+ format: selectedFormat
619
+ });
620
+ const catalogArtifact = createOptionalCatalogArtifact(
621
+ configExport,
622
+ report,
623
+ parsedArgs.outCatalog
624
+ );
625
+ const artifactPaths = await writeArtifacts({
626
+ cwd,
627
+ report,
628
+ catalogArtifact,
629
+ outputs: {
630
+ json: parsedArgs.outJson ?? configExport.outputs?.json,
631
+ markdown: parsedArgs.outMarkdown ?? configExport.outputs?.markdown,
632
+ catalog: parsedArgs.outCatalog ?? configExport.outputs?.catalog
633
+ }
634
+ });
635
+ return {
636
+ exitCode: report.gate.accepted ? 0 : 1,
637
+ skipped: false,
638
+ report,
639
+ catalogArtifact,
640
+ stdout,
641
+ artifactPaths
642
+ };
643
+ } catch (error) {
644
+ return cliFailure(error instanceof Error ? error.message : "Unknown CLI failure.");
645
+ }
646
+ }
647
+ function parseCliArgs(argv) {
648
+ const parsedArgs = {};
649
+ for (let index = 0; index < argv.length; index += 1) {
650
+ const arg = argv[index];
651
+ if (arg === "--") {
652
+ continue;
653
+ }
654
+ if (arg === "--help" || arg === "-h") {
655
+ parsedArgs.help = true;
656
+ continue;
657
+ }
658
+ if (arg === "--config") {
659
+ parsedArgs.configPath = requireValue(argv, index, arg);
660
+ index += 1;
661
+ continue;
662
+ }
663
+ if (arg === "--format") {
664
+ const format = requireValue(argv, index, arg);
665
+ if (format !== "markdown" && format !== "json") {
666
+ throw new Error("--format must be markdown or json.");
667
+ }
668
+ parsedArgs.format = format;
669
+ index += 1;
670
+ continue;
671
+ }
672
+ if (arg === "--out-json") {
673
+ parsedArgs.outJson = requireValue(argv, index, arg);
674
+ index += 1;
675
+ continue;
676
+ }
677
+ if (arg === "--out-md") {
678
+ parsedArgs.outMarkdown = requireValue(argv, index, arg);
679
+ index += 1;
680
+ continue;
681
+ }
682
+ if (arg === "--out-catalog") {
683
+ parsedArgs.outCatalog = requireValue(argv, index, arg);
684
+ index += 1;
685
+ continue;
686
+ }
687
+ if (arg === "--title") {
688
+ parsedArgs.title = requireValue(argv, index, arg);
689
+ index += 1;
690
+ continue;
691
+ }
692
+ throw new Error(`Unknown argument "${arg}".`);
693
+ }
694
+ return parsedArgs;
695
+ }
696
+ function requireValue(argv, index, flag) {
697
+ const value = argv[index + 1];
698
+ if (!value || value.startsWith("--")) {
699
+ throw new Error(`${flag} requires a value.`);
700
+ }
701
+ return value;
702
+ }
703
+ async function loadCliConfig(configPath, context) {
704
+ const configExport = await loadCliConfigDefault(configPath, context.cwd);
705
+ if (typeof configExport === "function") {
706
+ return configExport(context);
707
+ }
708
+ return configExport;
709
+ }
710
+ function isCliSkip(value) {
711
+ return !!value && typeof value === "object" && !Array.isArray(value) && value.skip === true && typeof value.reason === "string";
712
+ }
713
+ function assertCliConfig(value) {
714
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
715
+ throw new Error("x402 acceptance CLI config must export an object.");
716
+ }
717
+ if (!("acceptance" in value) || !value.acceptance || typeof value.acceptance !== "object") {
718
+ throw new Error("x402 acceptance CLI config requires acceptance options.");
719
+ }
720
+ const outputs = value.outputs;
721
+ if (outputs !== void 0 && (!outputs || typeof outputs !== "object" || Array.isArray(outputs) || outputs.json !== void 0 && typeof outputs.json !== "string" || outputs.markdown !== void 0 && typeof outputs.markdown !== "string" || outputs.catalog !== void 0 && typeof outputs.catalog !== "string")) {
722
+ throw new Error("x402 acceptance CLI outputs must contain string paths.");
723
+ }
724
+ const catalog = value.catalog;
725
+ if (catalog !== void 0) {
726
+ if (!catalog || typeof catalog !== "object" || Array.isArray(catalog)) {
727
+ throw new Error("x402 acceptance CLI catalog config must be an object.");
728
+ }
729
+ if (!("manifest" in catalog) || !catalog.manifest || typeof catalog.manifest !== "object") {
730
+ throw new Error("x402 acceptance CLI catalog config requires manifest.");
731
+ }
732
+ if (catalog.artifactId !== void 0 && typeof catalog.artifactId !== "string") {
733
+ throw new Error("x402 acceptance CLI catalog artifactId must be a string.");
734
+ }
735
+ if (catalog.generatedAt !== void 0 && typeof catalog.generatedAt !== "string") {
736
+ throw new Error("x402 acceptance CLI catalog generatedAt must be a string.");
737
+ }
738
+ }
739
+ }
740
+ function mergeForbiddenOutputValues(config) {
741
+ return [
742
+ ...config.acceptance.forbiddenOutputValues ?? [],
743
+ ...config.report?.forbiddenOutputValues ?? []
744
+ ];
745
+ }
746
+ function createOptionalCatalogArtifact(config, report, requestedCatalogOutput) {
747
+ if (!config.catalog) {
748
+ if (requestedCatalogOutput ?? config.outputs?.catalog) {
749
+ throw new Error(
750
+ "x402 acceptance CLI catalog output requires catalog manifest config."
751
+ );
752
+ }
753
+ return void 0;
754
+ }
755
+ return createProviderCatalogArtifact({
756
+ manifest: config.catalog.manifest,
757
+ acceptanceReport: report,
758
+ artifactId: config.catalog.artifactId,
759
+ generatedAt: config.catalog.generatedAt,
760
+ forbiddenOutputValues: mergeForbiddenOutputValues(config)
761
+ });
762
+ }
763
+ async function writeArtifacts(options) {
764
+ const artifactPaths = {};
765
+ if (options.outputs.json) {
766
+ const outputPath = resolve(options.cwd, options.outputs.json);
767
+ await writeArtifact(
768
+ outputPath,
769
+ formatX402ProviderAcceptanceReport(options.report, {
770
+ format: "json"
771
+ })
772
+ );
773
+ artifactPaths.json = outputPath;
774
+ }
775
+ if (options.outputs.markdown) {
776
+ const outputPath = resolve(options.cwd, options.outputs.markdown);
777
+ await writeArtifact(
778
+ outputPath,
779
+ formatX402ProviderAcceptanceReport(options.report, {
780
+ format: "markdown"
781
+ })
782
+ );
783
+ artifactPaths.markdown = outputPath;
784
+ }
785
+ if (options.outputs.catalog) {
786
+ if (!options.catalogArtifact) {
787
+ throw new Error(
788
+ "x402 acceptance CLI catalog output requires a catalog artifact."
789
+ );
790
+ }
791
+ const outputPath = resolve(options.cwd, options.outputs.catalog);
792
+ await writeArtifact(
793
+ outputPath,
794
+ formatProviderCatalogArtifact(options.catalogArtifact, {
795
+ format: "json"
796
+ })
797
+ );
798
+ artifactPaths.catalog = outputPath;
799
+ }
800
+ return artifactPaths;
801
+ }
802
+ async function writeArtifact(outputPath, body) {
803
+ await mkdir(dirname(outputPath), {
804
+ recursive: true
805
+ });
806
+ await writeFile(outputPath, body, "utf8");
807
+ }
808
+ function cliFailure(message) {
809
+ return {
810
+ exitCode: 2,
811
+ skipped: false,
812
+ stdout: "",
813
+ stderr: `${message}
814
+ ${USAGE}
815
+ `
816
+ };
817
+ }
818
+
819
+ export {
820
+ runX402ProviderAcceptance,
821
+ summarizeX402AcceptanceResult,
822
+ evaluateX402ProviderAcceptanceGate,
823
+ createX402ProviderAcceptanceReport,
824
+ formatX402ProviderAcceptanceReport,
825
+ runX402ProviderAcceptanceCli
826
+ };
827
+ //# sourceMappingURL=chunk-257Y7LN2.js.map