@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,1117 @@
1
+ import {
2
+ redactX402Secrets
3
+ } from "./chunk-NYTV263W.js";
4
+ import {
5
+ ProbeMeshError
6
+ } from "./chunk-2ASMVLG4.js";
7
+
8
+ // src/paymentOptions.ts
9
+ function resolveProviderPaymentOption(input) {
10
+ const options = getProviderPaymentOptions(input);
11
+ const candidates = options.filter((option) => optionSupportsCapability(option, input.capability)).map((option, index) => ({
12
+ option,
13
+ index,
14
+ cost: pricingToCost(resolvePaymentOptionPricing(option, input.capability) ?? resolvePricing(input.pricing, input.capability)),
15
+ receiptTypes: option.receiptTypes ?? []
16
+ }));
17
+ const filtered = candidates.filter(
18
+ ({ option, receiptTypes }) => optionMatchesPaymentPreferences(option, receiptTypes, input.paymentPreferences)
19
+ );
20
+ if (filtered.length === 0) {
21
+ return {
22
+ options,
23
+ reason: createNoPaymentOptionReason(input, candidates.length)
24
+ };
25
+ }
26
+ const selected = choosePaymentOption(
27
+ filtered,
28
+ input.paymentPreferences,
29
+ input.paymentStrategy
30
+ );
31
+ return {
32
+ options,
33
+ selection: {
34
+ providerId: input.providerId,
35
+ optionId: selected.option.id,
36
+ protocolMode: selected.option.protocolMode,
37
+ cost: selected.cost,
38
+ receiptTypes: [...selected.receiptTypes],
39
+ score: selected.score,
40
+ scoreReasons: [...selected.scoreReasons],
41
+ metadata: cloneSerializable(selected.option.metadata)
42
+ }
43
+ };
44
+ }
45
+ function getProviderPaymentOptions(input) {
46
+ if (input.paymentOptions && input.paymentOptions.length > 0) {
47
+ return cloneSerializable(input.paymentOptions);
48
+ }
49
+ return [
50
+ {
51
+ id: "default",
52
+ protocolMode: input.providerMode ?? "local",
53
+ capabilities: [...input.capabilities],
54
+ ...input.pricing !== void 0 ? { pricing: cloneSerializable(input.pricing) } : {},
55
+ receiptTypes: [...input.defaultReceiptTypes ?? []]
56
+ }
57
+ ];
58
+ }
59
+ function validateProviderPaymentOptions(paymentOptions, path, capabilities, errors) {
60
+ if (paymentOptions === void 0) {
61
+ return;
62
+ }
63
+ if (!Array.isArray(paymentOptions) || paymentOptions.length === 0) {
64
+ errors.push({
65
+ path,
66
+ message: "paymentOptions must be a non-empty array when provided."
67
+ });
68
+ return;
69
+ }
70
+ const seen = /* @__PURE__ */ new Set();
71
+ paymentOptions.forEach((option, index) => {
72
+ const optionPath = `${path}.${index}`;
73
+ if (!isRecord(option)) {
74
+ errors.push({
75
+ path: optionPath,
76
+ message: "payment option must be an object."
77
+ });
78
+ return;
79
+ }
80
+ validateNonEmptyString(option.id, `${optionPath}.id`, errors);
81
+ validateNonEmptyString(option.protocolMode, `${optionPath}.protocolMode`, errors);
82
+ if (typeof option.id === "string") {
83
+ if (seen.has(option.id)) {
84
+ errors.push({
85
+ path: `${optionPath}.id`,
86
+ message: `duplicate payment option "${option.id}".`
87
+ });
88
+ }
89
+ seen.add(option.id);
90
+ }
91
+ if (option.capabilities !== void 0) {
92
+ validateStringArray(option.capabilities, `${optionPath}.capabilities`, errors);
93
+ if (Array.isArray(option.capabilities)) {
94
+ for (const capability of option.capabilities) {
95
+ if (typeof capability === "string" && capability.length > 0 && !capabilities.includes(capability)) {
96
+ errors.push({
97
+ path: `${optionPath}.capabilities`,
98
+ message: `payment option capability "${capability}" is not declared by the provider.`
99
+ });
100
+ }
101
+ }
102
+ }
103
+ }
104
+ if (option.pricing !== void 0) {
105
+ validatePricingDeclaration(option.pricing, `${optionPath}.pricing`, errors);
106
+ }
107
+ if (option.receiptTypes !== void 0) {
108
+ if (!Array.isArray(option.receiptTypes) || option.receiptTypes.some((receiptType) => !isReceiptType(receiptType))) {
109
+ errors.push({
110
+ path: `${optionPath}.receiptTypes`,
111
+ message: "payment option receiptTypes must contain known receipt types."
112
+ });
113
+ }
114
+ }
115
+ if (option.metadata !== void 0 && !isRecord(option.metadata)) {
116
+ errors.push({
117
+ path: `${optionPath}.metadata`,
118
+ message: "payment option metadata must be an object when provided."
119
+ });
120
+ }
121
+ });
122
+ }
123
+ function validatePaymentPreferences(paymentPreferences, capability) {
124
+ if (paymentPreferences === void 0) {
125
+ return;
126
+ }
127
+ if (!isRecord(paymentPreferences)) {
128
+ throw new ProbeMeshError({
129
+ code: "invalid_request",
130
+ message: "paymentPreferences must be an object when provided.",
131
+ capability
132
+ });
133
+ }
134
+ validatePreferenceStringArray(
135
+ paymentPreferences.allowedProtocols,
136
+ "allowedProtocols",
137
+ capability
138
+ );
139
+ validatePreferenceStringArray(
140
+ paymentPreferences.preferredProtocols,
141
+ "preferredProtocols",
142
+ capability
143
+ );
144
+ validatePreferenceStringArray(
145
+ paymentPreferences.blockedProtocols,
146
+ "blockedProtocols",
147
+ capability
148
+ );
149
+ validatePreferenceStringArray(
150
+ paymentPreferences.allowedPaymentOptions,
151
+ "allowedPaymentOptions",
152
+ capability
153
+ );
154
+ validatePreferenceStringArray(
155
+ paymentPreferences.preferredPaymentOptions,
156
+ "preferredPaymentOptions",
157
+ capability
158
+ );
159
+ validatePreferenceStringArray(
160
+ paymentPreferences.blockedPaymentOptions,
161
+ "blockedPaymentOptions",
162
+ capability
163
+ );
164
+ if (paymentPreferences.requiredReceiptTypes !== void 0 && (!Array.isArray(paymentPreferences.requiredReceiptTypes) || paymentPreferences.requiredReceiptTypes.some((receiptType) => !isReceiptType(receiptType)))) {
165
+ throw new ProbeMeshError({
166
+ code: "invalid_request",
167
+ message: "paymentPreferences.requiredReceiptTypes must contain known receipt types.",
168
+ capability
169
+ });
170
+ }
171
+ }
172
+ function validatePaymentStrategy(paymentStrategy, capability) {
173
+ if (paymentStrategy === void 0) {
174
+ return;
175
+ }
176
+ if (!isRecord(paymentStrategy)) {
177
+ throw new ProbeMeshError({
178
+ code: "invalid_request",
179
+ message: "paymentStrategy must be an object when provided.",
180
+ capability
181
+ });
182
+ }
183
+ if (!isPaymentStrategyMode(paymentStrategy.mode)) {
184
+ throw new ProbeMeshError({
185
+ code: "invalid_request",
186
+ message: 'paymentStrategy.mode must be one of "provider_order", "lowest_cost", "preferred_protocol", or "receipt_coverage".',
187
+ capability
188
+ });
189
+ }
190
+ if (paymentStrategy.preferredReceiptTypes !== void 0 && (!Array.isArray(paymentStrategy.preferredReceiptTypes) || paymentStrategy.preferredReceiptTypes.some(
191
+ (receiptType) => !isReceiptType(receiptType)
192
+ ))) {
193
+ throw new ProbeMeshError({
194
+ code: "invalid_request",
195
+ message: "paymentStrategy.preferredReceiptTypes must contain known receipt types.",
196
+ capability
197
+ });
198
+ }
199
+ }
200
+ function mergePaymentPreferences(first, second) {
201
+ if (!first && !second) {
202
+ return void 0;
203
+ }
204
+ return compactPaymentPreferences({
205
+ allowedProtocols: intersectArrays(first?.allowedProtocols, second?.allowedProtocols),
206
+ preferredProtocols: second?.preferredProtocols ?? first?.preferredProtocols,
207
+ blockedProtocols: unionArrays(first?.blockedProtocols, second?.blockedProtocols),
208
+ allowedPaymentOptions: intersectArrays(
209
+ first?.allowedPaymentOptions,
210
+ second?.allowedPaymentOptions
211
+ ),
212
+ preferredPaymentOptions: second?.preferredPaymentOptions ?? first?.preferredPaymentOptions,
213
+ blockedPaymentOptions: unionArrays(
214
+ first?.blockedPaymentOptions,
215
+ second?.blockedPaymentOptions
216
+ ),
217
+ requiredReceiptTypes: unionArrays(
218
+ first?.requiredReceiptTypes,
219
+ second?.requiredReceiptTypes
220
+ )
221
+ });
222
+ }
223
+ function paymentSelectionToCost(selection) {
224
+ return selection?.cost;
225
+ }
226
+ function optionSupportsCapability(option, capability) {
227
+ return !option.capabilities || option.capabilities.includes(capability);
228
+ }
229
+ function optionMatchesPaymentPreferences(option, receiptTypes, preferences) {
230
+ if (!preferences) {
231
+ return true;
232
+ }
233
+ if (preferences.allowedProtocols && !preferences.allowedProtocols.includes(option.protocolMode)) {
234
+ return false;
235
+ }
236
+ if (preferences.blockedProtocols?.includes(option.protocolMode)) {
237
+ return false;
238
+ }
239
+ if (preferences.allowedPaymentOptions && !preferences.allowedPaymentOptions.includes(option.id)) {
240
+ return false;
241
+ }
242
+ if (preferences.blockedPaymentOptions?.includes(option.id)) {
243
+ return false;
244
+ }
245
+ const receiptSet = new Set(receiptTypes);
246
+ return (preferences.requiredReceiptTypes ?? []).every(
247
+ (receiptType) => receiptSet.has(receiptType)
248
+ );
249
+ }
250
+ function choosePaymentOption(candidates, preferences, strategy) {
251
+ const mode = strategy?.mode ?? "provider_order";
252
+ const ranked = [...candidates].sort(
253
+ (left, right) => comparePaymentOptions(left, right, preferences, strategy)
254
+ );
255
+ return ranked.map((candidate, rank) => ({
256
+ ...candidate,
257
+ score: rank,
258
+ scoreReasons: createScoreReasons(candidate, preferences, strategy, mode)
259
+ }))[0];
260
+ }
261
+ function preferenceIndex(preferences, value) {
262
+ const index = preferences.indexOf(value);
263
+ return index === -1 ? Number.MAX_SAFE_INTEGER : index;
264
+ }
265
+ function comparePaymentOptions(left, right, preferences, strategy) {
266
+ switch (strategy?.mode ?? "provider_order") {
267
+ case "lowest_cost":
268
+ return compareCost(left, right) || left.index - right.index;
269
+ case "preferred_protocol":
270
+ return comparePreferredProtocol(left, right, preferences) || compareCost(left, right) || left.index - right.index;
271
+ case "receipt_coverage":
272
+ return compareReceiptCoverage(left, right, preferences, strategy) || comparePreferredProtocol(left, right, preferences) || compareCost(left, right) || left.index - right.index;
273
+ case "provider_order":
274
+ return compareProviderOrder(left, right, preferences);
275
+ }
276
+ }
277
+ function compareProviderOrder(left, right, preferences) {
278
+ const optionPreference = preferences?.preferredPaymentOptions ?? [];
279
+ const protocolPreference = preferences?.preferredProtocols ?? [];
280
+ const optionPreferenceDelta = preferenceIndex(optionPreference, left.option.id) - preferenceIndex(optionPreference, right.option.id);
281
+ if (optionPreferenceDelta !== 0) {
282
+ return optionPreferenceDelta;
283
+ }
284
+ const protocolPreferenceDelta = preferenceIndex(protocolPreference, left.option.protocolMode) - preferenceIndex(protocolPreference, right.option.protocolMode);
285
+ if (protocolPreferenceDelta !== 0) {
286
+ return protocolPreferenceDelta;
287
+ }
288
+ return left.index - right.index;
289
+ }
290
+ function comparePreferredProtocol(left, right, preferences) {
291
+ const protocolPreference = preferences?.preferredProtocols ?? [];
292
+ return preferenceIndex(protocolPreference, left.option.protocolMode) - preferenceIndex(protocolPreference, right.option.protocolMode);
293
+ }
294
+ function compareCost(left, right) {
295
+ const leftCost = costSortValue(left.cost);
296
+ const rightCost = costSortValue(right.cost);
297
+ if (leftCost === rightCost) {
298
+ return 0;
299
+ }
300
+ return leftCost < rightCost ? -1 : 1;
301
+ }
302
+ function compareReceiptCoverage(left, right, preferences, strategy) {
303
+ return receiptCoverage(right, preferences, strategy) - receiptCoverage(left, preferences, strategy);
304
+ }
305
+ function receiptCoverage(candidate, preferences, strategy) {
306
+ const desiredReceiptTypes = strategy?.preferredReceiptTypes ?? preferences?.requiredReceiptTypes ?? [];
307
+ const receiptSet = new Set(candidate.receiptTypes);
308
+ if (desiredReceiptTypes.length > 0) {
309
+ return desiredReceiptTypes.filter((receiptType) => receiptSet.has(receiptType)).length;
310
+ }
311
+ return receiptSet.size;
312
+ }
313
+ function costSortValue(cost) {
314
+ return cost?.amountUsd ?? Number.POSITIVE_INFINITY;
315
+ }
316
+ function createScoreReasons(candidate, preferences, strategy, mode) {
317
+ const reasons = [`strategy:${mode}`];
318
+ if (mode === "provider_order") {
319
+ const preferredOptionIndex = preferenceIndex(
320
+ preferences?.preferredPaymentOptions ?? [],
321
+ candidate.option.id
322
+ );
323
+ const preferredProtocolIndex = preferenceIndex(
324
+ preferences?.preferredProtocols ?? [],
325
+ candidate.option.protocolMode
326
+ );
327
+ if (preferredOptionIndex !== Number.MAX_SAFE_INTEGER) {
328
+ reasons.push(`preferred_option:${candidate.option.id}`);
329
+ } else if (preferredProtocolIndex !== Number.MAX_SAFE_INTEGER) {
330
+ reasons.push(`preferred_protocol:${candidate.option.protocolMode}`);
331
+ } else {
332
+ reasons.push(`provider_order:${candidate.index}`);
333
+ }
334
+ }
335
+ if (mode === "lowest_cost" || mode === "preferred_protocol" || mode === "receipt_coverage") {
336
+ reasons.push(
337
+ candidate.cost ? `cost:${candidate.cost.amountUsd}` : "cost:unknown"
338
+ );
339
+ }
340
+ if (mode === "preferred_protocol") {
341
+ reasons.push(
342
+ isPreferredProtocol(candidate, preferences) ? `preferred_protocol:${candidate.option.protocolMode}` : `protocol:${candidate.option.protocolMode}`
343
+ );
344
+ }
345
+ if (mode === "receipt_coverage") {
346
+ const desiredReceiptTypes = strategy?.preferredReceiptTypes ?? preferences?.requiredReceiptTypes ?? [];
347
+ reasons.push(
348
+ desiredReceiptTypes.length > 0 ? `receipt_coverage:${receiptCoverage(candidate, preferences, strategy)}/${desiredReceiptTypes.length}` : `receipt_coverage:${candidate.receiptTypes.length}`
349
+ );
350
+ if (isPreferredProtocol(candidate, preferences)) {
351
+ reasons.push(`preferred_protocol:${candidate.option.protocolMode}`);
352
+ }
353
+ }
354
+ return reasons;
355
+ }
356
+ function isPreferredProtocol(candidate, preferences) {
357
+ return preferences?.preferredProtocols?.includes(candidate.option.protocolMode) ?? false;
358
+ }
359
+ function createNoPaymentOptionReason(input, capabilityCandidateCount) {
360
+ if (capabilityCandidateCount === 0) {
361
+ return `Provider "${input.providerId}" has no payment option for capability "${input.capability}".`;
362
+ }
363
+ return `Provider "${input.providerId}" has no payment option matching paymentPreferences for capability "${input.capability}".`;
364
+ }
365
+ function resolvePaymentOptionPricing(option, capability) {
366
+ return resolvePricing(option.pricing, capability);
367
+ }
368
+ function resolvePricing(pricing, capability) {
369
+ if (!pricing) {
370
+ return void 0;
371
+ }
372
+ if (isPricing(pricing)) {
373
+ return pricing;
374
+ }
375
+ const capabilityPricing = pricing[capability];
376
+ return isPricing(capabilityPricing) ? capabilityPricing : void 0;
377
+ }
378
+ function pricingToCost(pricing) {
379
+ if (!pricing) {
380
+ return void 0;
381
+ }
382
+ return {
383
+ amountUsd: pricing.amountUsd,
384
+ currency: pricing.currency ?? "USD",
385
+ unit: pricing.unit
386
+ };
387
+ }
388
+ function validatePreferenceStringArray(value, field, capability) {
389
+ if (value !== void 0 && (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0))) {
390
+ throw new ProbeMeshError({
391
+ code: "invalid_request",
392
+ message: `paymentPreferences.${field} must be an array of non-empty strings when provided.`,
393
+ capability
394
+ });
395
+ }
396
+ }
397
+ function validatePricingDeclaration(pricing, path, errors) {
398
+ if (!isRecord(pricing)) {
399
+ errors.push({
400
+ path,
401
+ message: "payment option pricing must be an object."
402
+ });
403
+ return;
404
+ }
405
+ if (isPricing(pricing)) {
406
+ validatePricing(pricing, path, errors);
407
+ return;
408
+ }
409
+ for (const [capability, capabilityPricing] of Object.entries(pricing)) {
410
+ validatePricing(capabilityPricing, `${path}.${capability}`, errors);
411
+ }
412
+ }
413
+ function validatePricing(pricing, path, errors) {
414
+ if (!isRecord(pricing)) {
415
+ errors.push({
416
+ path,
417
+ message: "payment option pricing entry must be an object."
418
+ });
419
+ return;
420
+ }
421
+ validateNonEmptyString(pricing.unit, `${path}.unit`, errors);
422
+ if (typeof pricing.amountUsd !== "number" || !Number.isFinite(pricing.amountUsd) || pricing.amountUsd < 0) {
423
+ errors.push({
424
+ path: `${path}.amountUsd`,
425
+ message: "amountUsd must be a non-negative number."
426
+ });
427
+ }
428
+ if (pricing.currency !== void 0 && typeof pricing.currency !== "string") {
429
+ errors.push({
430
+ path: `${path}.currency`,
431
+ message: "currency must be a string when provided."
432
+ });
433
+ }
434
+ }
435
+ function validateStringArray(value, path, errors) {
436
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string" || entry.length === 0)) {
437
+ errors.push({
438
+ path,
439
+ message: `${path} must be an array of non-empty strings.`
440
+ });
441
+ }
442
+ }
443
+ function validateNonEmptyString(value, path, errors) {
444
+ if (typeof value !== "string" || value.length === 0) {
445
+ errors.push({
446
+ path,
447
+ message: `${path} must be a non-empty string.`
448
+ });
449
+ }
450
+ }
451
+ function isPricing(value) {
452
+ return isRecord(value) && typeof value.unit === "string" && value.unit.length > 0 && typeof value.amountUsd === "number" && Number.isFinite(value.amountUsd) && value.amountUsd >= 0 && (value.currency === void 0 || typeof value.currency === "string");
453
+ }
454
+ function isReceiptType(value) {
455
+ return value === "payment_proof" || value === "settlement_confirmation" || value === "provider_delivery" || value === "provider_response_evidence" || value === "authorization_decision";
456
+ }
457
+ function isPaymentStrategyMode(value) {
458
+ return value === "provider_order" || value === "lowest_cost" || value === "preferred_protocol" || value === "receipt_coverage";
459
+ }
460
+ function compactPaymentPreferences(preferences) {
461
+ const entries = Object.entries(preferences).filter(
462
+ ([, value]) => value !== void 0 && (!Array.isArray(value) || value.length > 0)
463
+ );
464
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
465
+ }
466
+ function intersectArrays(first, second) {
467
+ if (first === void 0) {
468
+ return second === void 0 ? void 0 : [...second];
469
+ }
470
+ if (second === void 0) {
471
+ return [...first];
472
+ }
473
+ const secondValues = new Set(second);
474
+ return first.filter((value) => secondValues.has(value));
475
+ }
476
+ function unionArrays(first, second) {
477
+ const values = [...first ?? [], ...second ?? []];
478
+ return values.length > 0 ? [...new Set(values)] : void 0;
479
+ }
480
+ function isRecord(value) {
481
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
482
+ }
483
+ function cloneSerializable(value) {
484
+ if (value === void 0) {
485
+ return value;
486
+ }
487
+ return JSON.parse(JSON.stringify(value));
488
+ }
489
+
490
+ // src/providerKit/manifest.ts
491
+ var JSON_SCHEMA_HINT_KEYS = /* @__PURE__ */ new Set([
492
+ "$schema",
493
+ "$id",
494
+ "type",
495
+ "properties",
496
+ "required",
497
+ "items",
498
+ "enum",
499
+ "description",
500
+ "additionalProperties",
501
+ "oneOf",
502
+ "anyOf",
503
+ "allOf"
504
+ ]);
505
+ function validateProviderManifest(manifest) {
506
+ const errors = [];
507
+ if (!isRecord2(manifest)) {
508
+ return {
509
+ valid: false,
510
+ errors: [
511
+ {
512
+ path: "$",
513
+ message: "Provider manifest must be an object."
514
+ }
515
+ ]
516
+ };
517
+ }
518
+ validateNonEmptyString2(manifest.id, "id", errors);
519
+ validateNonEmptyString2(manifest.displayName, "displayName", errors);
520
+ validateCapabilityList(manifest.capabilities, errors);
521
+ validateNonEmptyString2(manifest.protocolMode, "protocolMode", errors);
522
+ validateProviderPaymentOptions(
523
+ manifest.paymentOptions,
524
+ "paymentOptions",
525
+ Array.isArray(manifest.capabilities) ? manifest.capabilities : [],
526
+ errors
527
+ );
528
+ validatePricingDeclaration2(
529
+ manifest.pricing,
530
+ "pricing",
531
+ manifest.capabilities,
532
+ errors
533
+ );
534
+ validateSchemaDeclaration(
535
+ manifest.inputSchema,
536
+ "inputSchema",
537
+ manifest.capabilities,
538
+ errors
539
+ );
540
+ validateSchemaDeclaration(
541
+ manifest.outputSchema,
542
+ "outputSchema",
543
+ manifest.capabilities,
544
+ errors
545
+ );
546
+ validateReceipts(manifest.receipts, errors);
547
+ if (manifest.limits !== void 0) {
548
+ validateLimits(manifest.limits, errors);
549
+ }
550
+ return {
551
+ valid: errors.length === 0,
552
+ errors
553
+ };
554
+ }
555
+ function assertProviderManifest(manifest) {
556
+ const result = validateProviderManifest(manifest);
557
+ if (result.valid) {
558
+ return;
559
+ }
560
+ throw new ProbeMeshError({
561
+ code: "invalid_request",
562
+ message: `Invalid provider manifest: ${formatValidationErrors(result.errors)}`
563
+ });
564
+ }
565
+ function isSharedJsonSchemaLike(value) {
566
+ if (!isRecord2(value)) {
567
+ return false;
568
+ }
569
+ return Object.keys(value).some((key) => JSON_SCHEMA_HINT_KEYS.has(key));
570
+ }
571
+ function isSharedPricing(value) {
572
+ return isRecord2(value) && typeof value.unit === "string" && value.unit.length > 0 && typeof value.amountUsd === "number";
573
+ }
574
+ function validateCapabilityList(capabilities, errors) {
575
+ if (!Array.isArray(capabilities) || capabilities.length === 0) {
576
+ errors.push({
577
+ path: "capabilities",
578
+ message: "capabilities must be a non-empty array."
579
+ });
580
+ return;
581
+ }
582
+ const seen = /* @__PURE__ */ new Set();
583
+ capabilities.forEach((capability, index) => {
584
+ if (typeof capability !== "string" || capability.length === 0) {
585
+ errors.push({
586
+ path: `capabilities.${index}`,
587
+ message: "capability ids must be non-empty strings."
588
+ });
589
+ return;
590
+ }
591
+ if (seen.has(capability)) {
592
+ errors.push({
593
+ path: `capabilities.${index}`,
594
+ message: `duplicate capability "${capability}".`
595
+ });
596
+ }
597
+ seen.add(capability);
598
+ });
599
+ }
600
+ function validatePricingDeclaration2(pricing, path, capabilities, errors) {
601
+ if (!isRecord2(pricing)) {
602
+ errors.push({
603
+ path,
604
+ message: "pricing must be an object."
605
+ });
606
+ return;
607
+ }
608
+ if (isSharedPricing(pricing)) {
609
+ validatePricing2(pricing, path, errors);
610
+ return;
611
+ }
612
+ if (!Array.isArray(capabilities)) {
613
+ return;
614
+ }
615
+ for (const capability of capabilities) {
616
+ if (typeof capability !== "string" || capability.length === 0) {
617
+ continue;
618
+ }
619
+ validatePricing2(pricing[capability], `${path}.${capability}`, errors);
620
+ }
621
+ }
622
+ function validatePricing2(pricing, path, errors) {
623
+ if (!isRecord2(pricing)) {
624
+ errors.push({
625
+ path,
626
+ message: "pricing entry must be an object."
627
+ });
628
+ return;
629
+ }
630
+ validateNonEmptyString2(pricing.unit, `${path}.unit`, errors);
631
+ if (typeof pricing.amountUsd !== "number" || !Number.isFinite(pricing.amountUsd) || pricing.amountUsd < 0) {
632
+ errors.push({
633
+ path: `${path}.amountUsd`,
634
+ message: "amountUsd must be a non-negative number."
635
+ });
636
+ }
637
+ if (pricing.currency !== void 0 && typeof pricing.currency !== "string") {
638
+ errors.push({
639
+ path: `${path}.currency`,
640
+ message: "currency must be a string when provided."
641
+ });
642
+ }
643
+ }
644
+ function validateSchemaDeclaration(schema, path, capabilities, errors) {
645
+ if (!isRecord2(schema)) {
646
+ errors.push({
647
+ path,
648
+ message: `${path} must be an object.`
649
+ });
650
+ return;
651
+ }
652
+ if (isSharedJsonSchemaLike(schema)) {
653
+ validateSchemaLike(schema, path, errors);
654
+ return;
655
+ }
656
+ if (!Array.isArray(capabilities)) {
657
+ return;
658
+ }
659
+ for (const capability of capabilities) {
660
+ if (typeof capability !== "string" || capability.length === 0) {
661
+ continue;
662
+ }
663
+ validateSchemaLike(schema[capability], `${path}.${capability}`, errors);
664
+ }
665
+ }
666
+ function validateSchemaLike(schema, path, errors) {
667
+ if (!isRecord2(schema)) {
668
+ errors.push({
669
+ path,
670
+ message: "schema entry must be an object."
671
+ });
672
+ return;
673
+ }
674
+ if (schema.type !== void 0 && typeof schema.type !== "string") {
675
+ errors.push({
676
+ path: `${path}.type`,
677
+ message: "schema type must be a string when provided."
678
+ });
679
+ }
680
+ if (schema.properties !== void 0 && !isRecord2(schema.properties)) {
681
+ errors.push({
682
+ path: `${path}.properties`,
683
+ message: "schema properties must be an object when provided."
684
+ });
685
+ }
686
+ if (schema.required !== void 0 && (!Array.isArray(schema.required) || schema.required.some((field) => typeof field !== "string"))) {
687
+ errors.push({
688
+ path: `${path}.required`,
689
+ message: "schema required must be an array of strings when provided."
690
+ });
691
+ }
692
+ }
693
+ function validateReceipts(receipts, errors) {
694
+ if (!isRecord2(receipts)) {
695
+ errors.push({
696
+ path: "receipts",
697
+ message: "receipts must be an object."
698
+ });
699
+ return;
700
+ }
701
+ validateBoolean(receipts.payment, "receipts.payment", errors);
702
+ validateBoolean(receipts.delivery, "receipts.delivery", errors);
703
+ validateBoolean(
704
+ receipts.responseEvidence,
705
+ "receipts.responseEvidence",
706
+ errors
707
+ );
708
+ }
709
+ function validateLimits(limits, errors) {
710
+ if (!isRecord2(limits)) {
711
+ errors.push({
712
+ path: "limits",
713
+ message: "limits must be an object when provided."
714
+ });
715
+ return;
716
+ }
717
+ const typedLimits = limits;
718
+ if (typedLimits.maxRequestsPerMinute !== void 0 && (!Number.isFinite(typedLimits.maxRequestsPerMinute) || typedLimits.maxRequestsPerMinute <= 0)) {
719
+ errors.push({
720
+ path: "limits.maxRequestsPerMinute",
721
+ message: "maxRequestsPerMinute must be a positive number when provided."
722
+ });
723
+ }
724
+ }
725
+ function validateNonEmptyString2(value, path, errors) {
726
+ if (typeof value !== "string" || value.length === 0) {
727
+ errors.push({
728
+ path,
729
+ message: `${path} must be a non-empty string.`
730
+ });
731
+ }
732
+ }
733
+ function validateBoolean(value, path, errors) {
734
+ if (typeof value !== "boolean") {
735
+ errors.push({
736
+ path,
737
+ message: `${path} must be a boolean.`
738
+ });
739
+ }
740
+ }
741
+ function isRecord2(value) {
742
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
743
+ }
744
+ function formatValidationErrors(errors) {
745
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
746
+ }
747
+
748
+ // src/providerCatalogArtifact.ts
749
+ var PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION = "probemesh.provider-catalog.v1";
750
+ function createProviderCatalogArtifact(options) {
751
+ assertProviderCatalogArtifactOptions(options);
752
+ const artifact = {
753
+ schemaVersion: PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION,
754
+ artifactId: options.artifactId ?? `${options.manifest.id}:${options.acceptanceReport.summary.callId ?? "unknown"}:catalog`,
755
+ generatedAt: options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
756
+ status: options.acceptanceReport.gate.accepted ? "ready" : "rejected",
757
+ provider: cloneSerializable2(options.manifest),
758
+ acceptance: {
759
+ title: options.acceptanceReport.title,
760
+ status: options.acceptanceReport.status,
761
+ gate: cloneSerializable2(options.acceptanceReport.gate),
762
+ failedChecks: [
763
+ ...options.acceptanceReport.summary.failedCheckNames
764
+ ],
765
+ receipts: cloneSerializable2(options.acceptanceReport.receipts),
766
+ safety: cloneSerializable2(options.acceptanceReport.safety),
767
+ retrySafety: cloneSerializable2(options.acceptanceReport.retrySafety),
768
+ route: cloneSerializable2(options.acceptanceReport.route),
769
+ timelineEventTypes: [
770
+ ...options.acceptanceReport.timelineEventTypes
771
+ ],
772
+ telemetryEventTypes: [
773
+ ...options.acceptanceReport.telemetryEventTypes
774
+ ],
775
+ errorCode: options.acceptanceReport.summary.errorCode
776
+ }
777
+ };
778
+ const sanitizedArtifact = sanitizeCatalogOutput(
779
+ artifact,
780
+ options.forbiddenOutputValues ?? []
781
+ );
782
+ assertProviderCatalogArtifact(sanitizedArtifact);
783
+ return sanitizedArtifact;
784
+ }
785
+ function formatProviderCatalogArtifact(artifact, options = {}) {
786
+ assertProviderCatalogArtifact(artifact);
787
+ if ((options.format ?? "json") === "markdown") {
788
+ return formatCatalogArtifactMarkdown(artifact);
789
+ }
790
+ return JSON.stringify(artifact, null, 2);
791
+ }
792
+ function validateProviderCatalogArtifact(artifact) {
793
+ const errors = [];
794
+ if (!isRecord3(artifact)) {
795
+ return {
796
+ valid: false,
797
+ errors: [
798
+ {
799
+ path: "$",
800
+ message: "Provider catalog artifact must be an object."
801
+ }
802
+ ]
803
+ };
804
+ }
805
+ if (artifact.schemaVersion !== PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION) {
806
+ errors.push({
807
+ path: "schemaVersion",
808
+ message: `schemaVersion must be "${PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION}".`
809
+ });
810
+ }
811
+ validateNonEmptyString3(artifact.artifactId, "artifactId", errors);
812
+ validateIsoTimestamp(artifact.generatedAt, "generatedAt", errors);
813
+ if (artifact.status !== "ready" && artifact.status !== "rejected") {
814
+ errors.push({
815
+ path: "status",
816
+ message: 'status must be "ready" or "rejected".'
817
+ });
818
+ }
819
+ const manifestValidation = validateProviderManifest(artifact.provider);
820
+ for (const manifestError of manifestValidation.errors) {
821
+ errors.push({
822
+ path: `provider.${manifestError.path}`,
823
+ message: manifestError.message
824
+ });
825
+ }
826
+ validateAcceptanceArtifact(artifact.acceptance, errors);
827
+ return {
828
+ valid: errors.length === 0,
829
+ errors
830
+ };
831
+ }
832
+ function assertProviderCatalogArtifact(artifact) {
833
+ const result = validateProviderCatalogArtifact(artifact);
834
+ if (result.valid) {
835
+ return;
836
+ }
837
+ throw new ProbeMeshError({
838
+ code: "invalid_request",
839
+ message: `Invalid provider catalog artifact: ${formatValidationErrors2(result.errors)}`
840
+ });
841
+ }
842
+ function assertProviderCatalogArtifactOptions(options) {
843
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
844
+ throw new ProbeMeshError({
845
+ code: "invalid_request",
846
+ message: "Provider catalog artifact options must be an object."
847
+ });
848
+ }
849
+ const manifestValidation = validateProviderManifest(options.manifest);
850
+ if (!manifestValidation.valid) {
851
+ throw new ProbeMeshError({
852
+ code: "invalid_request",
853
+ message: `Invalid provider catalog artifact manifest: ${formatValidationErrors2(
854
+ manifestValidation.errors
855
+ )}`
856
+ });
857
+ }
858
+ if (!options.acceptanceReport || typeof options.acceptanceReport !== "object" || Array.isArray(options.acceptanceReport)) {
859
+ throw new ProbeMeshError({
860
+ code: "invalid_request",
861
+ message: "Provider catalog artifact requires an acceptance report."
862
+ });
863
+ }
864
+ if (options.generatedAt !== void 0 && (typeof options.generatedAt !== "string" || Number.isNaN(Date.parse(options.generatedAt)))) {
865
+ throw new ProbeMeshError({
866
+ code: "invalid_request",
867
+ message: "Provider catalog artifact generatedAt must be an ISO timestamp."
868
+ });
869
+ }
870
+ if (options.artifactId !== void 0 && (typeof options.artifactId !== "string" || options.artifactId.length === 0)) {
871
+ throw new ProbeMeshError({
872
+ code: "invalid_request",
873
+ message: "Provider catalog artifact artifactId must be a non-empty string."
874
+ });
875
+ }
876
+ if (options.forbiddenOutputValues !== void 0 && (!Array.isArray(options.forbiddenOutputValues) || options.forbiddenOutputValues.some((value) => typeof value !== "string"))) {
877
+ throw new ProbeMeshError({
878
+ code: "invalid_request",
879
+ message: "Provider catalog artifact forbiddenOutputValues must be an array of strings."
880
+ });
881
+ }
882
+ }
883
+ function formatCatalogArtifactMarkdown(artifact) {
884
+ const lines = [
885
+ `# ${artifact.provider.displayName} Provider Catalog Artifact`,
886
+ "",
887
+ `Status: ${artifact.status}`,
888
+ `Schema: ${artifact.schemaVersion}`,
889
+ `Artifact ID: ${artifact.artifactId}`,
890
+ `Generated: ${artifact.generatedAt}`,
891
+ "",
892
+ "## Provider",
893
+ `- ID: ${artifact.provider.id}`,
894
+ `- Display name: ${artifact.provider.displayName}`,
895
+ `- Protocol: ${artifact.provider.protocolMode}`,
896
+ `- Capabilities: ${formatInlineList(artifact.provider.capabilities)}`,
897
+ "",
898
+ "## Acceptance",
899
+ `- Gate: ${artifact.acceptance.gate.status}`,
900
+ `- Result: ${artifact.acceptance.status}`,
901
+ `- Failed checks: ${formatInlineList(artifact.acceptance.failedChecks)}`,
902
+ `- Gate reasons: ${formatInlineList(artifact.acceptance.gate.reasons)}`,
903
+ "",
904
+ "## Receipts",
905
+ `- Total: ${artifact.acceptance.receipts.total}`,
906
+ `- Types: ${formatInlineList(artifact.acceptance.receipts.types)}`,
907
+ `- Providers: ${formatInlineList(artifact.acceptance.receipts.providers)}`,
908
+ `- Payment proof: ${String(artifact.acceptance.receipts.hasPaymentProof)}`,
909
+ `- Settlement confirmation: ${String(
910
+ artifact.acceptance.receipts.hasSettlementConfirmation
911
+ )}`,
912
+ `- Provider delivery: ${String(
913
+ artifact.acceptance.receipts.hasProviderDelivery
914
+ )}`,
915
+ "",
916
+ "## Safety",
917
+ `- Payment: ${artifact.acceptance.safety?.paymentStatus ?? "unknown"}`,
918
+ `- Settlement: ${artifact.acceptance.safety?.settlementStatus ?? "unknown"}`,
919
+ `- Delivery: ${artifact.acceptance.safety?.deliveryStatus ?? "unknown"}`,
920
+ `- Money may have moved: ${String(
921
+ artifact.acceptance.safety?.moneyMayHaveMoved ?? false
922
+ )}`,
923
+ "",
924
+ "## Retry Safety",
925
+ `- Retryable: ${String(artifact.acceptance.retrySafety?.retryable ?? false)}`,
926
+ `- Safe to auto retry: ${String(
927
+ artifact.acceptance.retrySafety?.safeToAutoRetry ?? false
928
+ )}`,
929
+ `- Reason: ${artifact.acceptance.retrySafety?.reason ?? "unknown"}`,
930
+ "",
931
+ "## Route And Timeline",
932
+ `- Selected provider: ${artifact.acceptance.route?.selectedProviderId ?? "none"}`,
933
+ `- Stop reason: ${artifact.acceptance.route?.stopReason ?? "none"}`,
934
+ `- Timeline events: ${formatInlineList(artifact.acceptance.timelineEventTypes)}`,
935
+ `- Telemetry events: ${formatInlineList(artifact.acceptance.telemetryEventTypes)}`
936
+ ];
937
+ return `${lines.join("\n")}
938
+ `;
939
+ }
940
+ function formatInlineList(values) {
941
+ return values && values.length > 0 ? values.join(", ") : "none";
942
+ }
943
+ function sanitizeCatalogOutput(value, forbiddenOutputValues) {
944
+ const forbiddenValues = forbiddenOutputValues.filter((entry) => entry.length > 0);
945
+ return redactX402Secrets(
946
+ replaceForbiddenValues(value, forbiddenValues, /* @__PURE__ */ new WeakSet())
947
+ );
948
+ }
949
+ function replaceForbiddenValues(value, forbiddenValues, seen) {
950
+ if (typeof value === "string") {
951
+ return forbiddenValues.reduce(
952
+ (current, forbidden) => current.split(forbidden).join("[REDACTED]"),
953
+ value
954
+ );
955
+ }
956
+ if (value === null || typeof value !== "object" || value instanceof Date) {
957
+ return value;
958
+ }
959
+ if (seen.has(value)) {
960
+ return "[Circular]";
961
+ }
962
+ seen.add(value);
963
+ if (Array.isArray(value)) {
964
+ const entries2 = value.map(
965
+ (entry) => replaceForbiddenValues(entry, forbiddenValues, seen)
966
+ );
967
+ seen.delete(value);
968
+ return entries2;
969
+ }
970
+ const entries = Object.fromEntries(
971
+ Object.entries(value).map(([key, entry]) => [
972
+ key,
973
+ replaceForbiddenValues(entry, forbiddenValues, seen)
974
+ ])
975
+ );
976
+ seen.delete(value);
977
+ return entries;
978
+ }
979
+ function cloneSerializable2(value) {
980
+ if (value === void 0) {
981
+ return value;
982
+ }
983
+ return JSON.parse(JSON.stringify(value));
984
+ }
985
+ function validateAcceptanceArtifact(acceptance, errors) {
986
+ if (!isRecord3(acceptance)) {
987
+ errors.push({
988
+ path: "acceptance",
989
+ message: "acceptance must be an object."
990
+ });
991
+ return;
992
+ }
993
+ validateNonEmptyString3(acceptance.title, "acceptance.title", errors);
994
+ if (acceptance.status !== "passed" && acceptance.status !== "failed") {
995
+ errors.push({
996
+ path: "acceptance.status",
997
+ message: 'acceptance.status must be "passed" or "failed".'
998
+ });
999
+ }
1000
+ if (!isRecord3(acceptance.gate)) {
1001
+ errors.push({
1002
+ path: "acceptance.gate",
1003
+ message: "acceptance.gate must be an object."
1004
+ });
1005
+ } else {
1006
+ if (typeof acceptance.gate.accepted !== "boolean") {
1007
+ errors.push({
1008
+ path: "acceptance.gate.accepted",
1009
+ message: "acceptance.gate.accepted must be a boolean."
1010
+ });
1011
+ }
1012
+ if (acceptance.gate.status !== "accepted" && acceptance.gate.status !== "rejected") {
1013
+ errors.push({
1014
+ path: "acceptance.gate.status",
1015
+ message: 'acceptance.gate.status must be "accepted" or "rejected".'
1016
+ });
1017
+ }
1018
+ }
1019
+ validateStringArray2(
1020
+ acceptance.failedChecks,
1021
+ "acceptance.failedChecks",
1022
+ errors
1023
+ );
1024
+ validateReceiptSummary(acceptance.receipts, errors);
1025
+ validateStringArray2(
1026
+ acceptance.timelineEventTypes,
1027
+ "acceptance.timelineEventTypes",
1028
+ errors
1029
+ );
1030
+ validateStringArray2(
1031
+ acceptance.telemetryEventTypes,
1032
+ "acceptance.telemetryEventTypes",
1033
+ errors
1034
+ );
1035
+ }
1036
+ function validateReceiptSummary(receipts, errors) {
1037
+ if (!isRecord3(receipts)) {
1038
+ errors.push({
1039
+ path: "acceptance.receipts",
1040
+ message: "acceptance.receipts must be an object."
1041
+ });
1042
+ return;
1043
+ }
1044
+ if (typeof receipts.total !== "number" || !Number.isFinite(receipts.total)) {
1045
+ errors.push({
1046
+ path: "acceptance.receipts.total",
1047
+ message: "acceptance.receipts.total must be a number."
1048
+ });
1049
+ }
1050
+ validateStringArray2(receipts.types, "acceptance.receipts.types", errors);
1051
+ validateStringArray2(
1052
+ receipts.providers,
1053
+ "acceptance.receipts.providers",
1054
+ errors
1055
+ );
1056
+ for (const key of [
1057
+ "hasPaymentProof",
1058
+ "hasSettlementConfirmation",
1059
+ "hasProviderDelivery"
1060
+ ]) {
1061
+ if (typeof receipts[key] !== "boolean") {
1062
+ errors.push({
1063
+ path: `acceptance.receipts.${key}`,
1064
+ message: `acceptance.receipts.${key} must be a boolean.`
1065
+ });
1066
+ }
1067
+ }
1068
+ }
1069
+ function validateStringArray2(value, path, errors) {
1070
+ if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
1071
+ errors.push({
1072
+ path,
1073
+ message: `${path} must be an array of strings.`
1074
+ });
1075
+ }
1076
+ }
1077
+ function validateNonEmptyString3(value, path, errors) {
1078
+ if (typeof value !== "string" || value.length === 0) {
1079
+ errors.push({
1080
+ path,
1081
+ message: `${path} must be a non-empty string.`
1082
+ });
1083
+ }
1084
+ }
1085
+ function validateIsoTimestamp(value, path, errors) {
1086
+ if (typeof value !== "string" || Number.isNaN(Date.parse(value))) {
1087
+ errors.push({
1088
+ path,
1089
+ message: `${path} must be an ISO timestamp string.`
1090
+ });
1091
+ }
1092
+ }
1093
+ function formatValidationErrors2(errors) {
1094
+ return errors.map((error) => `${error.path}: ${error.message}`).join("; ");
1095
+ }
1096
+ function isRecord3(value) {
1097
+ return !!value && typeof value === "object" && !Array.isArray(value);
1098
+ }
1099
+
1100
+ export {
1101
+ resolveProviderPaymentOption,
1102
+ getProviderPaymentOptions,
1103
+ validateProviderPaymentOptions,
1104
+ validatePaymentPreferences,
1105
+ validatePaymentStrategy,
1106
+ mergePaymentPreferences,
1107
+ paymentSelectionToCost,
1108
+ validateProviderManifest,
1109
+ assertProviderManifest,
1110
+ isSharedJsonSchemaLike,
1111
+ PROVIDER_CATALOG_ARTIFACT_SCHEMA_VERSION,
1112
+ createProviderCatalogArtifact,
1113
+ formatProviderCatalogArtifact,
1114
+ validateProviderCatalogArtifact,
1115
+ assertProviderCatalogArtifact
1116
+ };
1117
+ //# sourceMappingURL=chunk-3H7UGVI6.js.map