@nuanu-ai/agentify-contracts 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/card.d.ts ADDED
@@ -0,0 +1,423 @@
1
+ /**
2
+ * One product, in the shapes it has: the card the merchant publishes, the card
3
+ * an agent reads in a catalog, and the card its own merchant reads back.
4
+ *
5
+ * The published card comes first and everything the agent sees is drawn from
6
+ * it. The requirement that runs through every field follows from that: an
7
+ * agent holding only this card has to be able to assemble a correct purchase
8
+ * and know what it will get back. A field that fails that test is not a
9
+ * detail, it is a sale that ends in a refusal.
10
+ *
11
+ * The catalog id is not part of the published schema. We issue it when the
12
+ * card is published and hand it back in the result, so a card arriving with
13
+ * one is a card whose author is guessing at our numbering.
14
+ *
15
+ * The first two shapes share this file rather than being separated by
16
+ * audience, because what they have to be is in step with each other. Anything a
17
+ * merchant may publish has to project into something an agent can read, and
18
+ * anything the projection copies is a claim we make to whoever spends money on
19
+ * it. Kept apart, the rule that ties them would live in neither file.
20
+ *
21
+ * The third is not a projection at all and is here for the opposite reason: a
22
+ * merchant reading their own catalog is reading what they wrote, so the card
23
+ * travels whole, wrapped in the two facts they cannot have — the identifier we
24
+ * issued and the word it is selling under. A second projection would be one
25
+ * more shape to keep in step for no gain to anybody.
26
+ */
27
+ import { z } from "zod";
28
+ import type { ParamSpecInput } from "./param-spec.js";
29
+ import type { Money } from "./primitives.js";
30
+ /**
31
+ * When the product reaches the agent, and therefore when the money moves.
32
+ *
33
+ * `sync` — in the answer to the purchase, and the payment executes last, after
34
+ * the merchant has delivered. `async` — later, by a separate call, and the
35
+ * payment executes at the moment of purchase. `confirm` — the merchant is
36
+ * asked first, and the payment executes right after they say yes.
37
+ */
38
+ export declare const FulfillmentSchema: z.ZodEnum<{
39
+ sync: "sync";
40
+ async: "async";
41
+ confirm: "confirm";
42
+ }>;
43
+ /**
44
+ * How the price and availability of this card are asked for, if they are.
45
+ *
46
+ * `"handler"` is the default path: the question travels the same outgoing
47
+ * channel as the orders, and the merchant hosts nothing. The other form names
48
+ * an address, for merchants whose price is computed by a separate service that
49
+ * the order handler cannot reach.
50
+ *
51
+ * The address has to be https. The question and the answer carry a merchant's
52
+ * prices; over plain http they are readable and rewritable by anyone on the
53
+ * path, and a sale that went through at someone else's price would be
54
+ * indistinguishable from an honest one.
55
+ */
56
+ export declare const PriceCheckSchema: z.ZodUnion<readonly [z.ZodLiteral<"handler">, z.ZodObject<{
57
+ url: z.ZodURL;
58
+ }, z.core.$strict>]>;
59
+ /**
60
+ * The name the seller of a card is listed under, wherever a catalog names a
61
+ * seller rather than a product.
62
+ *
63
+ * It belongs to the merchant and not to any one card: a merchant sells under
64
+ * one name, and a per-card name would be one seller appearing as several. What
65
+ * holds it is the merchants table, so this schema is the rule alone, applied
66
+ * wherever a merchant's listing name is written down.
67
+ */
68
+ export declare const ServiceNameSchema: z.ZodString;
69
+ /**
70
+ * The words a merchant puts on one product so an agent searching a catalog can
71
+ * find it.
72
+ *
73
+ * They describe this product and not the seller, which is why they sit on the
74
+ * card. At most five, because the catalog keeps the first five and drops the
75
+ * rest without a word.
76
+ */
77
+ export declare const TagsSchema: z.ZodArray<z.ZodString>;
78
+ /**
79
+ * Both deadlines are shown to the agent before it pays, which is why a card
80
+ * may only carry the ones its own mode uses. A synchronous card advertising a
81
+ * delivery deadline would be advertising a wait that never happens — and the
82
+ * wait for a synchronous answer is our system-wide budget, the same for every
83
+ * product, so it has no field here at all.
84
+ */
85
+ export declare const CardSchema: z.ZodObject<{
86
+ merchant_item_id: z.ZodString;
87
+ title: z.ZodString;
88
+ description: z.ZodString;
89
+ price: z.ZodPreprocess<z.ZodObject<{
90
+ amount: z.ZodString;
91
+ currency: z.ZodString;
92
+ }, z.core.$strict>>;
93
+ params: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
94
+ type: z.ZodEnum<{
95
+ string: "string";
96
+ number: "number";
97
+ boolean: "boolean";
98
+ integer: "integer";
99
+ }>;
100
+ required: z.ZodOptional<z.ZodBoolean>;
101
+ title: z.ZodOptional<z.ZodString>;
102
+ }, z.core.$strict>>>>;
103
+ result: z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
104
+ type: z.ZodEnum<{
105
+ string: "string";
106
+ number: "number";
107
+ boolean: "boolean";
108
+ integer: "integer";
109
+ }>;
110
+ required: z.ZodOptional<z.ZodBoolean>;
111
+ title: z.ZodOptional<z.ZodString>;
112
+ }, z.core.$strict>>>;
113
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
114
+ fulfillment: z.ZodDefault<z.ZodEnum<{
115
+ sync: "sync";
116
+ async: "async";
117
+ confirm: "confirm";
118
+ }>>;
119
+ price_check: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"handler">, z.ZodObject<{
120
+ url: z.ZodURL;
121
+ }, z.core.$strict>]>>;
122
+ confirm_deadline_seconds: z.ZodOptional<z.ZodInt>;
123
+ fulfill_deadline_seconds: z.ZodOptional<z.ZodInt>;
124
+ }, z.core.$strict>;
125
+ export type Fulfillment = z.infer<typeof FulfillmentSchema>;
126
+ export type PriceCheck = z.infer<typeof PriceCheckSchema>;
127
+ export type Card = z.infer<typeof CardSchema>;
128
+ /**
129
+ * A card as a merchant may write it, before the short forms are opened out.
130
+ *
131
+ * It is the input face of the one schema above rather than a second schema, and
132
+ * it is spelled out by hand because zod cannot describe it: the short forms are
133
+ * read by a step whose own input is `unknown`, so inference would hand a
134
+ * merchant no help at all where this hands them the two spellings each field
135
+ * takes.
136
+ *
137
+ * What that costs is one place to keep in step, and it is bounded: everything
138
+ * except the four fields named below is taken from `Card` itself, so a field
139
+ * added to a card appears here without anybody remembering to add it. A test
140
+ * holds the other direction — a canonical card is a thing a merchant may write.
141
+ *
142
+ * `Card` is what everything else uses. This type is for the call that publishes
143
+ * and for nothing else; nothing is ever read back in this shape.
144
+ */
145
+ export type CardInput = Omit<Card, "price" | "params" | "result" | "fulfillment"> & {
146
+ /** `{ amount, currency }`, or the two as one string: `'5.00 USD'`. */
147
+ price: Money | string;
148
+ /** Each field whole, or written as its type word alone: `email: 'string'`. */
149
+ params?: ParamSpecInput;
150
+ result: ParamSpecInput;
151
+ /** Left out on a card that is delivered in the answer to the purchase. */
152
+ fulfillment?: Fulfillment;
153
+ };
154
+ /**
155
+ * The check an agent's purchase parameters are held to, for this card.
156
+ *
157
+ * The compiler underneath takes a direction, and a direction is a string a
158
+ * caller can get backwards: compiling a card's result as a purchase silently
159
+ * restores the hole where a delivery promises nothing. These two take the card
160
+ * instead, so the only place that knows which declaration is which is the
161
+ * place that picks.
162
+ */
163
+ export declare const purchaseCheckFor: (card: Card) => z.ZodType;
164
+ /** The check this card's delivery is held to. */
165
+ export declare const deliveryCheckFor: (card: Card) => z.ZodType;
166
+ export declare const PublicCardSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
167
+ id: z.ZodString;
168
+ title: z.ZodString;
169
+ description: z.ZodString;
170
+ price: z.ZodObject<{
171
+ amount: z.ZodString;
172
+ currency: z.ZodString;
173
+ }, z.core.$strict>;
174
+ as_of: z.ZodISODateTime;
175
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
176
+ type: z.ZodEnum<{
177
+ string: "string";
178
+ number: "number";
179
+ boolean: "boolean";
180
+ integer: "integer";
181
+ }>;
182
+ required: z.ZodOptional<z.ZodBoolean>;
183
+ title: z.ZodOptional<z.ZodString>;
184
+ }, z.core.$strict>>>;
185
+ result: z.ZodRecord<z.ZodString, z.ZodObject<{
186
+ type: z.ZodEnum<{
187
+ string: "string";
188
+ number: "number";
189
+ boolean: "boolean";
190
+ integer: "integer";
191
+ }>;
192
+ required: z.ZodOptional<z.ZodBoolean>;
193
+ title: z.ZodOptional<z.ZodString>;
194
+ }, z.core.$strict>>;
195
+ price_checked_at_purchase: z.ZodBoolean;
196
+ fulfillment: z.ZodLiteral<"sync">;
197
+ }, z.core.$strict>, z.ZodObject<{
198
+ id: z.ZodString;
199
+ title: z.ZodString;
200
+ description: z.ZodString;
201
+ price: z.ZodObject<{
202
+ amount: z.ZodString;
203
+ currency: z.ZodString;
204
+ }, z.core.$strict>;
205
+ as_of: z.ZodISODateTime;
206
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
207
+ type: z.ZodEnum<{
208
+ string: "string";
209
+ number: "number";
210
+ boolean: "boolean";
211
+ integer: "integer";
212
+ }>;
213
+ required: z.ZodOptional<z.ZodBoolean>;
214
+ title: z.ZodOptional<z.ZodString>;
215
+ }, z.core.$strict>>>;
216
+ result: z.ZodRecord<z.ZodString, z.ZodObject<{
217
+ type: z.ZodEnum<{
218
+ string: "string";
219
+ number: "number";
220
+ boolean: "boolean";
221
+ integer: "integer";
222
+ }>;
223
+ required: z.ZodOptional<z.ZodBoolean>;
224
+ title: z.ZodOptional<z.ZodString>;
225
+ }, z.core.$strict>>;
226
+ price_checked_at_purchase: z.ZodBoolean;
227
+ fulfillment: z.ZodLiteral<"async">;
228
+ fulfill_deadline_seconds: z.ZodOptional<z.ZodInt>;
229
+ }, z.core.$strict>, z.ZodObject<{
230
+ id: z.ZodString;
231
+ title: z.ZodString;
232
+ description: z.ZodString;
233
+ price: z.ZodObject<{
234
+ amount: z.ZodString;
235
+ currency: z.ZodString;
236
+ }, z.core.$strict>;
237
+ as_of: z.ZodISODateTime;
238
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
239
+ type: z.ZodEnum<{
240
+ string: "string";
241
+ number: "number";
242
+ boolean: "boolean";
243
+ integer: "integer";
244
+ }>;
245
+ required: z.ZodOptional<z.ZodBoolean>;
246
+ title: z.ZodOptional<z.ZodString>;
247
+ }, z.core.$strict>>>;
248
+ result: z.ZodRecord<z.ZodString, z.ZodObject<{
249
+ type: z.ZodEnum<{
250
+ string: "string";
251
+ number: "number";
252
+ boolean: "boolean";
253
+ integer: "integer";
254
+ }>;
255
+ required: z.ZodOptional<z.ZodBoolean>;
256
+ title: z.ZodOptional<z.ZodString>;
257
+ }, z.core.$strict>>;
258
+ price_checked_at_purchase: z.ZodBoolean;
259
+ fulfillment: z.ZodLiteral<"confirm">;
260
+ confirm_deadline_seconds: z.ZodOptional<z.ZodInt>;
261
+ fulfill_deadline_seconds: z.ZodOptional<z.ZodInt>;
262
+ }, z.core.$strict>], "fulfillment">;
263
+ export type PublicCard = z.infer<typeof PublicCardSchema>;
264
+ /**
265
+ * The card as an agent reads it, built from the card the merchant published.
266
+ *
267
+ * It exists so there is one projection rather than one per caller. The
268
+ * decision about what an agent may see is made once, here, and it is made by
269
+ * naming each field that is copied. Built the other way — copy the card, then
270
+ * remove what is internal — a field added to the published card would reach
271
+ * every agent by default, and the first anybody heard of it would be a
272
+ * merchant's pricing address in a public catalog.
273
+ *
274
+ * The two things the card cannot know are passed in: the catalog identifier we
275
+ * issued when it was published, and the moment its price was published.
276
+ */
277
+ export declare const publicCardOf: (card: Card, issued: {
278
+ readonly id: string;
279
+ readonly as_of: string;
280
+ }) => PublicCard;
281
+ /**
282
+ * One card as a discovery catalog reads it: what an agent that has never seen
283
+ * our own catalog finds when it searches somewhere else.
284
+ *
285
+ * This is the second projection of a card and it sits beside the first because
286
+ * the two have to be read together. Both are claims we make to somebody about
287
+ * to spend money, both are built by naming what is copied rather than by
288
+ * copying the card and removing what is internal, and a field added to a card
289
+ * has to be considered against both or it reaches one audience by accident.
290
+ *
291
+ * What comes out is not a wire document of ours. It is the material an x402
292
+ * payment challenge is assembled from — the resource block, an example of the
293
+ * purchase body, the JSON Schema that body is held to, and an example of what a
294
+ * delivery carries — and the assembling is done at the edge, by the protocol's
295
+ * own library, from exactly these pieces. Keeping the projection here and the
296
+ * assembly there is what stops this package growing a payment library's
297
+ * dependency tree, which is the merchant SDK's dependency tree (ADR-0003 §8).
298
+ *
299
+ * Two decisions inside are worth reading before the code.
300
+ *
301
+ * The card's title is not sent. The resource block has one field of prose and
302
+ * the card has two, and joining a merchant's headline to a merchant's
303
+ * description with punctuation of our own would be us writing their listing for
304
+ * them. The description is the field a card writes for a program to read, so it
305
+ * is the one that goes.
306
+ *
307
+ * The examples are shapes rather than facts. A card declares the types of what
308
+ * it takes and what it returns and carries no example values, so what goes out
309
+ * is every declared field holding a value that stands for its type and nothing
310
+ * more. That is a claim we can keep — a test holds the input example to this
311
+ * card's own purchase check and the output example to its own delivery check,
312
+ * so what we publish is something our own door would accept — and it is not a
313
+ * claim about anybody's real data, which we do not have and will not invent.
314
+ */
315
+ export interface BazaarDeclaration {
316
+ /** The resource block: what is being paid for, and who is selling it. */
317
+ readonly resource: {
318
+ /** The canonical address of this resource, exactly as it was given. */
319
+ readonly url: string;
320
+ readonly description: string;
321
+ readonly mimeType: string;
322
+ readonly serviceName?: string;
323
+ readonly tags?: readonly string[];
324
+ };
325
+ /** An example purchase body, in the shape this gateway takes one. */
326
+ readonly input: Record<string, unknown>;
327
+ /** The JSON Schema that body is held to, derived from the card's `params`. */
328
+ readonly inputSchema: Record<string, unknown>;
329
+ /** An example of what arrives on delivery, derived from the card's `result`. */
330
+ readonly output: {
331
+ readonly example: Record<string, unknown>;
332
+ };
333
+ }
334
+ /**
335
+ * The card as a discovery catalog reads it.
336
+ *
337
+ * The two things a card cannot know are passed in: the address this resource
338
+ * answers at, which is pinned by whoever runs the gateway rather than worked
339
+ * out from a request, and the name its seller is listed under, which belongs to
340
+ * the merchant. A seller with no listing name and a card with no tags leave
341
+ * those fields out altogether — an empty string and an empty list are values a
342
+ * catalog would render, and the absence is the only way to say that nobody
343
+ * named one.
344
+ */
345
+ export declare const bazaarDeclarationOf: (card: Card, listed: {
346
+ readonly url: string;
347
+ readonly serviceName: string | null;
348
+ }) => BazaarDeclaration;
349
+ /**
350
+ * One card as the merchant who published it reads it back.
351
+ *
352
+ * The public catalog answers none of what a merchant needs from their own
353
+ * catalog. It is unscoped, so nothing in it says which entries are theirs; it
354
+ * carries our identifier in place of their key; and a card that is off sale is
355
+ * not in it at all, which is precisely the card a merchant is looking for when
356
+ * they go to put it back on sale.
357
+ *
358
+ * So the card travels whole rather than as a third projection. Everything the
359
+ * merchant wrote is theirs already, and copying a subset of it here would be
360
+ * one more shape to hold in step with the published card — the drift the
361
+ * projection above exists to prevent once, repeated for no gain.
362
+ *
363
+ * Two fields say where the card stands, and they are two rather than one for a
364
+ * reason that is invisible from the shape. `selling` is what a purchase of this
365
+ * card meets right now, and it is the same word the order machine is given at
366
+ * the birth of an order, so a card reading "paused" here is a card that refuses
367
+ * new orders there. `paused` says whether the pause is this card's own. They
368
+ * differ exactly when the merchant has stopped all selling: every card then
369
+ * reads `selling: "paused"`, and only the ones with `paused: true` are still
370
+ * paused after the merchant starts selling again. A merchant given only the
371
+ * first would press resume on a card and watch nothing change.
372
+ */
373
+ export declare const MerchantCardSchema: z.ZodObject<{
374
+ id: z.ZodString;
375
+ as_of: z.ZodISODateTime;
376
+ card: z.ZodObject<{
377
+ merchant_item_id: z.ZodString;
378
+ title: z.ZodString;
379
+ description: z.ZodString;
380
+ price: z.ZodPreprocess<z.ZodObject<{
381
+ amount: z.ZodString;
382
+ currency: z.ZodString;
383
+ }, z.core.$strict>>;
384
+ params: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
385
+ type: z.ZodEnum<{
386
+ string: "string";
387
+ number: "number";
388
+ boolean: "boolean";
389
+ integer: "integer";
390
+ }>;
391
+ required: z.ZodOptional<z.ZodBoolean>;
392
+ title: z.ZodOptional<z.ZodString>;
393
+ }, z.core.$strict>>>>;
394
+ result: z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
395
+ type: z.ZodEnum<{
396
+ string: "string";
397
+ number: "number";
398
+ boolean: "boolean";
399
+ integer: "integer";
400
+ }>;
401
+ required: z.ZodOptional<z.ZodBoolean>;
402
+ title: z.ZodOptional<z.ZodString>;
403
+ }, z.core.$strict>>>;
404
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
405
+ fulfillment: z.ZodDefault<z.ZodEnum<{
406
+ sync: "sync";
407
+ async: "async";
408
+ confirm: "confirm";
409
+ }>>;
410
+ price_check: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"handler">, z.ZodObject<{
411
+ url: z.ZodURL;
412
+ }, z.core.$strict>]>>;
413
+ confirm_deadline_seconds: z.ZodOptional<z.ZodInt>;
414
+ fulfill_deadline_seconds: z.ZodOptional<z.ZodInt>;
415
+ }, z.core.$strict>;
416
+ selling: z.ZodEnum<{
417
+ open: "open";
418
+ paused: "paused";
419
+ departed: "departed";
420
+ }>;
421
+ paused: z.ZodBoolean;
422
+ }, z.core.$strict>;
423
+ export type MerchantCard = z.infer<typeof MerchantCardSchema>;