@domino-sdk/relay 1.11.1 → 1.14.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 (50) hide show
  1. package/README.md +1 -0
  2. package/build.mjs +15 -0
  3. package/dist/accounts-5ciAkCMP.d.ts +147 -0
  4. package/dist/{activity-CNiPDPK6.d.ts → activity-D_R3J-gU.d.ts} +115 -115
  5. package/dist/attempt-captures-DZldPZJc.d.ts +285 -0
  6. package/dist/authoring.d.ts +49 -47
  7. package/dist/authoring.js +6 -4
  8. package/dist/{automatic-outcomes-kPIDv6X_.d.ts → automatic-outcomes-6lJGnSDe.d.ts} +1 -1
  9. package/dist/browser.d.ts +8 -7
  10. package/dist/browser.js +7 -6
  11. package/dist/capability-error-oTd3eYFH.d.ts +151 -0
  12. package/dist/chunk-2UAVZCMH.js +314 -0
  13. package/dist/chunk-5TS3OAWS.js +470 -0
  14. package/dist/{chunk-PUDL4JBY.js → chunk-6DD7DVNQ.js} +2 -2
  15. package/dist/{chunk-AGFUDCNM.js → chunk-C3CB4WIQ.js} +1 -1
  16. package/dist/{chunk-T657WO56.js → chunk-LLMJ2SUT.js} +6 -2
  17. package/dist/chunk-NIYCAW2I.js +79 -0
  18. package/dist/chunk-UJACD6K2.js +987 -0
  19. package/dist/{chunk-XK5E4HAS.js → chunk-VBHFJH3P.js} +80 -28
  20. package/dist/chunk-W335CWYJ.js +53 -0
  21. package/dist/{chunk-X7ECZ3AK.js → chunk-XMBM2XD5.js} +1 -1
  22. package/dist/{chunk-2K2QBPAD.js → chunk-ZLYBUM7K.js} +6 -4
  23. package/dist/{client-fUSERMAC.d.ts → client-BTd_CyX3.d.ts} +26 -6
  24. package/dist/{groups-BK8ts2yK.d.ts → groups-4Jb3uYFO.d.ts} +1 -1
  25. package/dist/{images-aw6W7vFZ.d.ts → images-D5kpqHxv.d.ts} +1 -1
  26. package/dist/index.d.ts +9 -8
  27. package/dist/index.js +8 -6
  28. package/dist/{capability-error-ty3SqD_b.d.ts → integrations-Cr9EhGI_.d.ts} +1 -149
  29. package/dist/internal.d.ts +32 -5
  30. package/dist/internal.js +8 -3
  31. package/dist/{offers-C2FANzrG.d.ts → offers-BFI5t-e-.d.ts} +2 -2
  32. package/dist/{pages-Chb6OZSB.d.ts → pages-nIoMT9J3.d.ts} +1 -1
  33. package/dist/{participant-activity-DkL3nY5a.d.ts → participant-activity-DYdUUhw2.d.ts} +1 -0
  34. package/dist/portal-proxy.js +1 -1
  35. package/dist/react/index.d.ts +246 -177
  36. package/dist/react/index.js +954 -383
  37. package/dist/{referral-reward-kinds-M3f0PdiR.d.ts → referral-reward-kinds-DnvQXL8L.d.ts} +100 -3
  38. package/dist/{schema-DEM8y8Fm.d.ts → schema-K-Pg5lPz.d.ts} +1 -1
  39. package/dist/schema.d.ts +316 -314
  40. package/dist/schema.js +16 -14
  41. package/dist/server/index.d.ts +2546 -377
  42. package/dist/server/index.js +594 -841
  43. package/dist/{sign-in-options-iWOp9puZ.d.ts → sign-in-options-DBjMzgnu.d.ts} +2 -2
  44. package/dist/submission-input-CPIsJt-_.d.ts +146 -0
  45. package/dist/testing.d.ts +641 -0
  46. package/dist/testing.js +1282 -0
  47. package/package.json +6 -2
  48. package/dist/chunk-OCXGG75K.js +0 -171
  49. package/dist/chunk-ZFABFKIY.js +0 -1295
  50. package/dist/submission-input-BbBJTVlT.d.ts +0 -290
@@ -0,0 +1,641 @@
1
+ import { bv as memberIdentitySchema, cC as trackerQuerySchema, cy as trackerPageSchema, cL as trackerSummarySchema, aD as TrackerContentQuery, ck as trackerContentSchema, bA as photoResultSchema, C as TextReviewInput, R as Reward, F as Decision, az as TrackerAttribution, o as Tracker, p as TrackerData, V as ContentBody, z as TrackerTriggerContext, a1 as TrackerPage } from './schema-K-Pg5lPz.js';
2
+ import { z } from 'zod';
3
+ import { l as discordMemberSchema, o as discordMessageSchema } from './accounts-5ciAkCMP.js';
4
+ import { b as CapabilityFailure, x as xConnectionSchema, j as xProfileSchema, i as xPostSchema } from './capability-error-oTd3eYFH.js';
5
+ export { C as CapabilityError } from './capability-error-oTd3eYFH.js';
6
+ import { f as ImageReference, n as imageInspectionSchema, j as imageComparisonSchema, q as imageSightingsSchema } from './images-D5kpqHxv.js';
7
+ import { u as linkedWalletSchema, z as walletBalanceSchema } from './wallet-CDyo-U4n.js';
8
+ export { A as AttemptCapture, C as CapturedFact } from './attempt-captures-DZldPZJc.js';
9
+
10
+ /** One project time-zone change: from `effectiveAt` on, days are counted in `timeZone`. */
11
+ type CalendarSegment = {
12
+ effectiveAt: number;
13
+ timeZone: string;
14
+ };
15
+
16
+ /** Every capability wire request, validated as the API Worker validates it before answering. */
17
+ declare const capabilityRequestSchemas: {
18
+ "wallet-balance": z.ZodObject<{
19
+ kind: z.ZodLiteral<"wallet-balance">;
20
+ chain: z.ZodUnion<readonly [z.ZodLiteral<"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp">, z.ZodCustom<`eip155:${number}`, `eip155:${number}`>, z.ZodCustom<`cosmos:${string}`, `cosmos:${string}`>]>;
21
+ token: z.ZodNullable<z.ZodString>;
22
+ address: z.ZodNullable<z.ZodString>;
23
+ }, z.core.$strict>;
24
+ "tracker-content": z.ZodObject<{
25
+ kind: z.ZodLiteral<"tracker-content">;
26
+ reference: z.ZodString;
27
+ query: z.ZodObject<{
28
+ id: z.ZodString;
29
+ observation: z.ZodString;
30
+ }, z.core.$strict>;
31
+ }, z.core.$strict>;
32
+ x: z.ZodObject<{
33
+ kind: z.ZodLiteral<"x">;
34
+ input: z.ZodDiscriminatedUnion<[z.ZodObject<{
35
+ operation: z.ZodLiteral<"connection">;
36
+ }, z.core.$strict>, z.ZodObject<{
37
+ operation: z.ZodLiteral<"profile">;
38
+ }, z.core.$strict>, z.ZodObject<{
39
+ operation: z.ZodLiteral<"post">;
40
+ postId: z.ZodString;
41
+ }, z.core.$strict>, z.ZodObject<{
42
+ operation: z.ZodLiteral<"follows">;
43
+ userId: z.ZodString;
44
+ }, z.core.$strict>, z.ZodObject<{
45
+ operation: z.ZodLiteral<"reposted">;
46
+ postId: z.ZodString;
47
+ }, z.core.$strict>], "operation">;
48
+ }, z.core.$strict>;
49
+ image: z.ZodObject<{
50
+ kind: z.ZodLiteral<"image">;
51
+ input: z.ZodDiscriminatedUnion<[z.ZodObject<{
52
+ operation: z.ZodLiteral<"inspect">;
53
+ image: z.ZodUnion<readonly [z.ZodObject<{
54
+ evidence: z.ZodString;
55
+ }, z.core.$strict>, z.ZodObject<{
56
+ x: z.ZodLiteral<"profile">;
57
+ }, z.core.$strict>, z.ZodObject<{
58
+ x: z.ZodLiteral<"post">;
59
+ postId: z.ZodString;
60
+ index: z.ZodDefault<z.ZodNumber>;
61
+ }, z.core.$strict>, z.ZodObject<{
62
+ asset: z.ZodString;
63
+ }, z.core.$strict>]>;
64
+ }, z.core.$strict>, z.ZodObject<{
65
+ operation: z.ZodLiteral<"compare">;
66
+ images: z.ZodTuple<[z.ZodUnion<readonly [z.ZodObject<{
67
+ evidence: z.ZodString;
68
+ }, z.core.$strict>, z.ZodObject<{
69
+ x: z.ZodLiteral<"profile">;
70
+ }, z.core.$strict>, z.ZodObject<{
71
+ x: z.ZodLiteral<"post">;
72
+ postId: z.ZodString;
73
+ index: z.ZodDefault<z.ZodNumber>;
74
+ }, z.core.$strict>, z.ZodObject<{
75
+ asset: z.ZodString;
76
+ }, z.core.$strict>]>, z.ZodUnion<readonly [z.ZodObject<{
77
+ evidence: z.ZodString;
78
+ }, z.core.$strict>, z.ZodObject<{
79
+ x: z.ZodLiteral<"profile">;
80
+ }, z.core.$strict>, z.ZodObject<{
81
+ x: z.ZodLiteral<"post">;
82
+ postId: z.ZodString;
83
+ index: z.ZodDefault<z.ZodNumber>;
84
+ }, z.core.$strict>, z.ZodObject<{
85
+ asset: z.ZodString;
86
+ }, z.core.$strict>]>], null>;
87
+ }, z.core.$strict>, z.ZodObject<{
88
+ operation: z.ZodLiteral<"review">;
89
+ images: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
90
+ evidence: z.ZodString;
91
+ }, z.core.$strict>, z.ZodObject<{
92
+ x: z.ZodLiteral<"profile">;
93
+ }, z.core.$strict>, z.ZodObject<{
94
+ x: z.ZodLiteral<"post">;
95
+ postId: z.ZodString;
96
+ index: z.ZodDefault<z.ZodNumber>;
97
+ }, z.core.$strict>, z.ZodObject<{
98
+ asset: z.ZodString;
99
+ }, z.core.$strict>]>>;
100
+ criteria: z.ZodString;
101
+ }, z.core.$strict>, z.ZodObject<{
102
+ operation: z.ZodLiteral<"extract">;
103
+ image: z.ZodUnion<readonly [z.ZodObject<{
104
+ evidence: z.ZodString;
105
+ }, z.core.$strict>, z.ZodObject<{
106
+ x: z.ZodLiteral<"profile">;
107
+ }, z.core.$strict>, z.ZodObject<{
108
+ x: z.ZodLiteral<"post">;
109
+ postId: z.ZodString;
110
+ index: z.ZodDefault<z.ZodNumber>;
111
+ }, z.core.$strict>, z.ZodObject<{
112
+ asset: z.ZodString;
113
+ }, z.core.$strict>]>;
114
+ fields: z.ZodRecord<z.ZodString, z.ZodObject<{
115
+ type: z.ZodEnum<{
116
+ string: "string";
117
+ number: "number";
118
+ boolean: "boolean";
119
+ }>;
120
+ description: z.ZodString;
121
+ }, z.core.$strict>>;
122
+ }, z.core.$strict>, z.ZodObject<{
123
+ operation: z.ZodLiteral<"seen">;
124
+ image: z.ZodUnion<readonly [z.ZodObject<{
125
+ evidence: z.ZodString;
126
+ }, z.core.$strict>, z.ZodObject<{
127
+ x: z.ZodLiteral<"profile">;
128
+ }, z.core.$strict>, z.ZodObject<{
129
+ x: z.ZodLiteral<"post">;
130
+ postId: z.ZodString;
131
+ index: z.ZodDefault<z.ZodNumber>;
132
+ }, z.core.$strict>, z.ZodObject<{
133
+ asset: z.ZodString;
134
+ }, z.core.$strict>]>;
135
+ maxDistance: z.ZodDefault<z.ZodNumber>;
136
+ }, z.core.$strict>], "operation">;
137
+ }, z.core.$strict>;
138
+ text: z.ZodObject<{
139
+ text: z.ZodString;
140
+ criteria: z.ZodString;
141
+ kind: z.ZodLiteral<"text">;
142
+ }, z.core.$strict>;
143
+ "tracker-records": z.ZodObject<{
144
+ reference: z.ZodString;
145
+ query: z.ZodObject<{
146
+ author: z.ZodOptional<z.ZodString>;
147
+ member: z.ZodOptional<z.ZodString>;
148
+ verified: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodPipe<z.ZodEnum<{
149
+ true: "true";
150
+ false: "false";
151
+ }>, z.ZodTransform<boolean, "true" | "false">>]>>;
152
+ since: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
153
+ until: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
154
+ removed: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodPipe<z.ZodEnum<{
155
+ true: "true";
156
+ false: "false";
157
+ }>, z.ZodTransform<boolean, "true" | "false">>]>>;
158
+ minLikes: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
159
+ minViews: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
160
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
161
+ cursor: z.ZodOptional<z.ZodString>;
162
+ includeEvidence: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodPipe<z.ZodEnum<{
163
+ true: "true";
164
+ false: "false";
165
+ }>, z.ZodTransform<boolean, "true" | "false">>]>>;
166
+ }, z.core.$strict>;
167
+ asOf: z.ZodNumber;
168
+ kind: z.ZodLiteral<"tracker-records">;
169
+ }, z.core.$strict>;
170
+ "tracker-summary": z.ZodObject<{
171
+ reference: z.ZodString;
172
+ query: z.ZodObject<{
173
+ author: z.ZodOptional<z.ZodString>;
174
+ member: z.ZodOptional<z.ZodString>;
175
+ verified: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodPipe<z.ZodEnum<{
176
+ true: "true";
177
+ false: "false";
178
+ }>, z.ZodTransform<boolean, "true" | "false">>]>>;
179
+ since: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
180
+ until: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
181
+ removed: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodPipe<z.ZodEnum<{
182
+ true: "true";
183
+ false: "false";
184
+ }>, z.ZodTransform<boolean, "true" | "false">>]>>;
185
+ minLikes: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
186
+ minViews: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
187
+ limit: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
188
+ cursor: z.ZodOptional<z.ZodString>;
189
+ includeEvidence: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodPipe<z.ZodEnum<{
190
+ true: "true";
191
+ false: "false";
192
+ }>, z.ZodTransform<boolean, "true" | "false">>]>>;
193
+ }, z.core.$strict>;
194
+ asOf: z.ZodNumber;
195
+ kind: z.ZodLiteral<"tracker-summary">;
196
+ }, z.core.$strict>;
197
+ photo: z.ZodObject<{
198
+ kind: z.ZodLiteral<"photo">;
199
+ criteria: z.ZodString;
200
+ image: z.ZodOptional<z.ZodString>;
201
+ }, z.core.$strict>;
202
+ discord: z.ZodObject<{
203
+ kind: z.ZodLiteral<"discord">;
204
+ input: z.ZodUnion<readonly [z.ZodObject<{}, z.core.$strict>, z.ZodObject<{
205
+ channelId: z.ZodString;
206
+ messageId: z.ZodString;
207
+ }, z.core.$strict>]>;
208
+ }, z.core.$strict>;
209
+ "wallet-list": z.ZodObject<{
210
+ kind: z.ZodLiteral<"wallet-list">;
211
+ }, z.core.$strict>;
212
+ "member-identities": z.ZodObject<{
213
+ kind: z.ZodLiteral<"member-identities">;
214
+ }, z.core.$strict>;
215
+ };
216
+ type CapabilityKind = keyof typeof capabilityRequestSchemas;
217
+ type CapabilityRequest = {
218
+ [K in CapabilityKind]: z.output<(typeof capabilityRequestSchemas)[K]>;
219
+ }[CapabilityKind];
220
+
221
+ /** A result as a fake writes it: Relay's result schema fills defaults before quest code reads it. */
222
+ type Result<S extends z.ZodType> = z.input<S>;
223
+ /**
224
+ * A fake capability answer: the value the reader resolves with, or a function of the call's
225
+ * arguments that returns it. Throw a `CapabilityError` from the function to fail the call as
226
+ * Relay would, such as `new CapabilityError("provider-unavailable", "X is unavailable")`.
227
+ */
228
+ type FakeAnswer<A extends unknown[], R> = R | ((...args: A) => R | Promise<R>);
229
+ /** A wallet balance query as Relay receives it: the chain is canonical CAIP-2. */
230
+ type WalletBalanceRequest = {
231
+ chain: string;
232
+ token: string | null;
233
+ address: string | null;
234
+ };
235
+ /** A tracker read as Relay receives it: defaults applied, and `asOf` set (`eligibleAt` unless given). */
236
+ type TrackerReadRequest = z.output<typeof trackerQuerySchema> & {
237
+ asOf: number;
238
+ };
239
+ /** The fake answers of one tracker, by reader method. */
240
+ type TrackerFacts = {
241
+ records?: FakeAnswer<[
242
+ query: TrackerReadRequest
243
+ ], Result<typeof trackerPageSchema>>;
244
+ summary?: FakeAnswer<[
245
+ query: TrackerReadRequest
246
+ ], Result<typeof trackerSummarySchema>>;
247
+ content?: FakeAnswer<[
248
+ query: TrackerContentQuery
249
+ ], Result<typeof trackerContentSchema> | null>;
250
+ };
251
+ /**
252
+ * Fake answers for the evaluator's capabilities, keyed like the evaluation context: `member`,
253
+ * `wallet`, `x`, `discord`, `trackers` (by tracker key), `images` and `review`.
254
+ *
255
+ * Reads of the member's own accounts default to a member who has linked nothing:
256
+ * `member.identities()`, `wallet.list()`, `wallet.balance()`, `x.connection()`, `x.profile()`,
257
+ * `x.follows()`, `x.reposted()` and `discord.member()` resolve to null. Once the test links an
258
+ * account (`wallet.list` or `x.connection` set to a value), supply every read of it the quest
259
+ * makes. Every other read (an X post, a Discord message, trackers, images and AI review) needs an
260
+ * answer: a call without one fails the run.
261
+ *
262
+ * Answers pass the result schemas Relay applies before quest code sees them, and arrive as JSON,
263
+ * as in a hosted run.
264
+ *
265
+ * @compat input
266
+ */
267
+ type TestFacts = {
268
+ member?: {
269
+ identities?: FakeAnswer<[], Result<typeof memberIdentitySchema>[] | null>;
270
+ };
271
+ wallet?: {
272
+ list?: FakeAnswer<[], Result<typeof linkedWalletSchema>[] | null>;
273
+ balance?: FakeAnswer<[
274
+ query: WalletBalanceRequest
275
+ ], Result<typeof walletBalanceSchema> | null>;
276
+ };
277
+ x?: {
278
+ connection?: FakeAnswer<[], Result<typeof xConnectionSchema> | null>;
279
+ profile?: FakeAnswer<[], Result<typeof xProfileSchema> | null>;
280
+ post?: FakeAnswer<[
281
+ input: {
282
+ postId: string;
283
+ }
284
+ ], Result<typeof xPostSchema> | null>;
285
+ follows?: FakeAnswer<[input: {
286
+ userId: string;
287
+ }], boolean | null>;
288
+ reposted?: FakeAnswer<[input: {
289
+ postId: string;
290
+ }], boolean | null>;
291
+ };
292
+ discord?: {
293
+ member?: FakeAnswer<[], Result<typeof discordMemberSchema> | null>;
294
+ message?: FakeAnswer<[
295
+ input: {
296
+ channelId: string;
297
+ messageId: string;
298
+ }
299
+ ], Result<typeof discordMessageSchema> | null>;
300
+ };
301
+ trackers?: Record<string, TrackerFacts>;
302
+ images?: {
303
+ inspect?: FakeAnswer<[
304
+ image: ImageReference
305
+ ], Result<typeof imageInspectionSchema>>;
306
+ compare?: FakeAnswer<[
307
+ a: ImageReference,
308
+ b: ImageReference
309
+ ], Result<typeof imageComparisonSchema>>;
310
+ review?: FakeAnswer<[
311
+ options: {
312
+ images: ImageReference[];
313
+ criteria: string;
314
+ }
315
+ ], Result<typeof photoResultSchema>>;
316
+ extract?: FakeAnswer<[
317
+ options: {
318
+ image: ImageReference;
319
+ fields: Record<string, unknown>;
320
+ }
321
+ ], {
322
+ values: Record<string, unknown>;
323
+ reason: string;
324
+ }>;
325
+ seen?: FakeAnswer<[
326
+ image: ImageReference,
327
+ options: {
328
+ maxDistance?: number;
329
+ }
330
+ ], Result<typeof imageSightingsSchema>>;
331
+ };
332
+ review?: {
333
+ text?: FakeAnswer<[
334
+ options: TextReviewInput
335
+ ], Result<typeof photoResultSchema>>;
336
+ photo?: FakeAnswer<[
337
+ options: {
338
+ image?: string;
339
+ criteria: string;
340
+ }
341
+ ], Result<typeof photoResultSchema>>;
342
+ };
343
+ };
344
+ /** A capability outcome as Relay captures it: the value, or the failure quest code receives. */
345
+ type CapabilityOutcome = {
346
+ value: unknown;
347
+ } | {
348
+ error: CapabilityFailure;
349
+ };
350
+ /** A mistake in the test's setup, not in quest code. `runQuest` reports it even when quest code catches it. */
351
+ declare class TestSetupError extends Error {
352
+ constructor(message: string);
353
+ }
354
+
355
+ /** The time a run starts at unless the test sets `now`: 2026-01-01T00:00:00Z. */
356
+ declare const defaultNow: number;
357
+ /** The member a run evaluates unless the test or its tracker observation names one. */
358
+ declare const defaultMember = "member_test";
359
+ /** The attempt ID that seeds a run's randomness unless the test sets `seed`. */
360
+ declare const defaultSeed = "attempt_test";
361
+ /**
362
+ * A quest handle from `defineQuest` or `defineQuestType`, as the testing kit uses it.
363
+ *
364
+ * @compat input
365
+ */
366
+ type TestableQuest = {
367
+ readonly key: string;
368
+ describe(settings: unknown): {
369
+ values: unknown;
370
+ rewards: Reward[];
371
+ humanReview: boolean;
372
+ integrations: readonly string[];
373
+ trigger: unknown;
374
+ };
375
+ evaluate(context: never): Promise<Decision>;
376
+ };
377
+ /** The host context `quest.evaluate` takes: what Relay's evaluator runtime passes it. */
378
+ type QuestHostContext<Q extends TestableQuest> = Q["evaluate"] extends (context: infer C) => unknown ? C : never;
379
+ /**
380
+ * The evidence a quest's trigger takes, as a test passes it: `{ value }` for text and URL quests,
381
+ * `{ photo }` (an evidence ID) for photo quests, `{ answers }` for quizzes. `kind` is optional:
382
+ * the kit fills it from the trigger.
383
+ */
384
+ type QuestInputOf<Q extends TestableQuest> = QuestHostContext<Q> extends {
385
+ input: infer I;
386
+ } ? I extends {
387
+ kind: infer K;
388
+ } ? Omit<I, "kind"> & {
389
+ kind?: K;
390
+ } : I : never;
391
+ /** @compat input */
392
+ type RunQuestOptions<Q extends TestableQuest = TestableQuest> = {
393
+ /** Setting values, as an operator enters them in Console. Omitted settings take their defaults. */
394
+ settings?: Record<string, unknown>;
395
+ /**
396
+ * The evaluated member's ID. Defaults to the member a `tracker` observation is attributed to,
397
+ * else `member_test`.
398
+ */
399
+ member?: string;
400
+ /**
401
+ * The submitted evidence of a manual quest: `{ value }`, `{ photo }` or `{ answers }`. Relay's
402
+ * submission checks apply, such as a text quest's `minLength`.
403
+ */
404
+ input?: QuestInputOf<Q>;
405
+ /**
406
+ * The pinned tracker observation of a tracker-triggered quest. Build it with
407
+ * `trackerObservation(tracker, { data })`.
408
+ */
409
+ tracker?: unknown;
410
+ /** A content quest's performance stage: the metric sample to evaluate. */
411
+ performance?: {
412
+ metrics: Record<string, number>;
413
+ /** When the sample was observed. Defaults to `now`. */
414
+ observedAt?: number;
415
+ /** The rewards content evaluation selected. Defaults to the published rewards. */
416
+ rewards?: Reward[];
417
+ };
418
+ /**
419
+ * The run's start time, `ctx.now`; `Date.now()` and `new Date()` return it during the evaluation.
420
+ * Defaults to 2026-01-01T00:00:00Z.
421
+ */
422
+ now?: number | Date;
423
+ /**
424
+ * When a manual quest's attempt was admitted, `ctx.eligibleAt`. Defaults to `now`. A
425
+ * tracker-triggered attempt takes its observation's `occurredAt`.
426
+ */
427
+ eligibleAt?: number | Date;
428
+ /** The project time zone `ctx.calendar` counts days in. Defaults to UTC. */
429
+ timeZone?: string;
430
+ /** Project time-zone changes, oldest first; overrides `timeZone`. */
431
+ calendar?: readonly CalendarSegment[];
432
+ /**
433
+ * Seeds `Math.random()`, `crypto.getRandomValues()` and `crypto.randomUUID()`; a hosted run uses
434
+ * the attempt ID.
435
+ */
436
+ seed?: string;
437
+ /** Fake answers for the capabilities the quest reads. */
438
+ facts?: TestFacts;
439
+ };
440
+ /**
441
+ * One capability call, as Relay captures it for replay.
442
+ *
443
+ * @compat output
444
+ */
445
+ type CapabilityCall = {
446
+ sequence: number;
447
+ request: CapabilityRequest;
448
+ outcome: CapabilityOutcome;
449
+ };
450
+ /**
451
+ * The published release a run used: what `describe` returned for the settings.
452
+ *
453
+ * @compat output
454
+ */
455
+ type TestRelease = {
456
+ values: unknown;
457
+ rewards: Reward[];
458
+ humanReview: boolean;
459
+ integrations: readonly string[];
460
+ };
461
+ /** @compat output */
462
+ type TestContext<Q extends TestableQuest = TestableQuest> = {
463
+ /** The host context to pass to `quest.evaluate`. */
464
+ context: QuestHostContext<Q>;
465
+ /** The capability calls quest code has made so far, in order. */
466
+ calls: CapabilityCall[];
467
+ release: TestRelease;
468
+ /** The run's start time and seed. */
469
+ now: number;
470
+ seed: string;
471
+ };
472
+ /** @compat output */
473
+ type QuestRun = {
474
+ decision: Decision;
475
+ calls: CapabilityCall[];
476
+ release: TestRelease;
477
+ };
478
+ /**
479
+ * Builds the host context `quest.evaluate` takes, with fake readers that answer from `facts`. Use
480
+ * it to call `quest.evaluate` yourself; `runQuest` also freezes the clock, seeds randomness and
481
+ * checks the decision as Relay does.
482
+ */
483
+ declare function createTestContext<Q extends TestableQuest>(quest: Q, options?: RunQuestOptions<Q>): TestContext<Q>;
484
+ /**
485
+ * Evaluates a quest locally the way Relay's hosted runtime does: the quest's published settings,
486
+ * rewards and review setting, `ctx.now` and `Date` frozen at `now`, randomness seeded by `seed`,
487
+ * capability readers answered from `facts` and checked against Relay's capability contracts, and
488
+ * the decision's rewards checked against the published bundle.
489
+ *
490
+ * Resolves with the decision and every capability call. Rejects with what quest code threw, such
491
+ * as an uncaught `CapabilityError` (Relay retries a retryable one), or with a `TestSetupError` for
492
+ * a call the facts cannot answer.
493
+ */
494
+ declare function runQuest<Q extends TestableQuest>(quest: Q, options?: RunQuestOptions<Q>): Promise<QuestRun>;
495
+
496
+ type Kind = Decision["kind"];
497
+ type DecisionOf<K extends Kind> = Extract<Decision, {
498
+ kind: K;
499
+ }>;
500
+ /** Thrown by `expectAccept` and its siblings when a decision is not the expected one. */
501
+ declare class DecisionAssertionError extends Error {
502
+ readonly decision: Decision;
503
+ constructor(message: string, decision: Decision);
504
+ }
505
+ /** Asserts the run accepted and returns the accept decision, with its rewards and completion key. */
506
+ declare function expectAccept(run: QuestRun | Decision): DecisionOf<"accept">;
507
+ /** Asserts the run rejected, optionally with a reason equal to a string or matching a pattern. */
508
+ declare function expectReject(run: QuestRun | Decision, reason?: string | RegExp): DecisionOf<"reject">;
509
+ /** Asserts the run went to human review, optionally with a reason equal to a string or matching a pattern. */
510
+ declare function expectReview(run: QuestRun | Decision, reason?: string | RegExp): DecisionOf<"review">;
511
+ /** Asserts the run deferred, optionally with a reason equal to a string or matching a pattern. */
512
+ declare function expectDefer(run: QuestRun | Decision, reason?: string | RegExp): DecisionOf<"defer">;
513
+ /** Asserts the run recorded progress, optionally with a reason equal to a string or matching a pattern. */
514
+ declare function expectProgress(run: QuestRun | Decision, reason?: string | RegExp): DecisionOf<"progress">;
515
+
516
+ /**
517
+ * One observation of a tracker record, as a tracker-triggered quest's attempt pins it.
518
+ *
519
+ * @compat input
520
+ */
521
+ type TrackerObservationInput<D, B> = {
522
+ /** The record's data, of the tracker's data type. */
523
+ data: D;
524
+ /** The member Relay attributed the record to. Defaults to `member_test`. */
525
+ member?: string;
526
+ /** The record's ID in its source. Defaults to `record_test`. */
527
+ id?: string;
528
+ /** When the activity happened; the attempt's `eligibleAt`. Defaults to 2026-01-01. */
529
+ occurredAt?: number | Date;
530
+ /** When Relay observed this version of the record. Defaults to `occurredAt`. */
531
+ observedAt?: number | Date;
532
+ /** The record's author account. Defaults to an unverified `author_test`. */
533
+ author?: {
534
+ id: string;
535
+ verified: boolean | null;
536
+ kind?: string;
537
+ } | null;
538
+ /** The record account the attempt pays. Defaults to `"author"`. */
539
+ beneficiary?: string;
540
+ /** The verified link Relay attributed the record through. Defaults to the member itself. */
541
+ account?: TrackerAttribution["account"];
542
+ /** On a content source: the content body this observation carries. */
543
+ body?: B;
544
+ /** On a quest that requires enrollment: when the member enrolled. */
545
+ enrolledAt?: number | Date;
546
+ /** Whether the source reported the record removed. */
547
+ removed?: boolean;
548
+ };
549
+ /**
550
+ * Builds the pinned observation a tracker-triggered quest evaluates: `runQuest(quest, { tracker:
551
+ * trackerObservation(messages, { data: { channelId: "123", ... } }) })`. `data` has the tracker's
552
+ * data type, and the result is checked against the shape Relay pins.
553
+ */
554
+ declare function trackerObservation<T extends Tracker>(tracker: T, observation: TrackerObservationInput<TrackerData<T>, ContentBody<T>>): TrackerTriggerContext<TrackerData<T>>;
555
+ /**
556
+ * One stored record of a tracker, as `ctx.trackers.records()` returns it.
557
+ *
558
+ * @compat input
559
+ */
560
+ type TrackerRecordInput<D> = {
561
+ /** The record's data, of the tracker's data type. */
562
+ data: D;
563
+ /** The record's ID in its source. Defaults to `record_<position>`. */
564
+ id?: string;
565
+ /** When the activity happened. Defaults to 2026-01-01. */
566
+ occurredAt?: number | Date;
567
+ /** When Relay observed this version of the record. Defaults to `occurredAt`. */
568
+ observedAt?: number | Date;
569
+ /** The record's author account. Defaults to an unverified `author_test`. */
570
+ author?: {
571
+ id: string;
572
+ verified: boolean | null;
573
+ kind?: string;
574
+ } | null;
575
+ /** Whether the source reported the record removed. */
576
+ removed?: boolean;
577
+ };
578
+ /**
579
+ * Builds a page of tracker records, as a `facts.trackers[key].records` answer: `trackerPage(posts,
580
+ * [{ data: { amount: 5 } }])`. `data` has the tracker's data type; the tracker's status says it is
581
+ * published, idle and fully synced. The page is checked against the shape Relay returns.
582
+ */
583
+ declare function trackerPage<T extends Tracker>(tracker: T, records: readonly TrackerRecordInput<TrackerData<T>>[], options?: {
584
+ nextCursor?: string | null;
585
+ total?: number;
586
+ }): TrackerPage<TrackerData<T>>;
587
+
588
+ /** @compat input */
589
+ type ReplayOptions = {
590
+ /**
591
+ * Answers for calls the capture cannot answer: a call the captured run did not make, one whose
592
+ * request changed, or a retryable failure Relay did not keep. Without them, the replay stops at
593
+ * the first such call.
594
+ */
595
+ facts?: TestFacts;
596
+ };
597
+ /**
598
+ * The first call the capture could not answer.
599
+ *
600
+ * @compat output
601
+ */
602
+ type ReplayDivergence = {
603
+ sequence: number;
604
+ /**
605
+ * `"new"`: the captured run made no such call. `"changed"`: it sent another request.
606
+ * `"uncaptured"`: its answer was a retryable failure Relay did not keep.
607
+ */
608
+ reason: "new" | "changed" | "uncaptured";
609
+ /** The request the captured run sent at this position; null for a new call. */
610
+ recorded: Record<string, unknown> | null;
611
+ replayed: CapabilityRequest;
612
+ };
613
+ /** @compat output */
614
+ type AttemptReplay = {
615
+ /** What the current quest code decides; null when the replay stopped at a divergence. */
616
+ decision: Decision | null;
617
+ /** What quest code decided in the captured run; null when it had decided nothing. */
618
+ recorded: Decision | null;
619
+ /**
620
+ * Whether the decision differs from the recorded one: its kind, reason, rewards or completion
621
+ * key. Null when either is missing.
622
+ */
623
+ changed: boolean | null;
624
+ /** The first call the capture could not answer, or null when it answered every call. */
625
+ divergence: ReplayDivergence | null;
626
+ calls: CapabilityCall[];
627
+ };
628
+ /**
629
+ * Evaluates current quest code against a captured attempt: the release's settings and rewards,
630
+ * the attempt's input, clock, seed and calendar, and the captured capability answers, as a retry
631
+ * of that evaluation run would. Get the capture with `management.attempts.capture(attempt)` or
632
+ * `domino quests replay <attempt> --out <file>`; Relay serves captures from the test environment
633
+ * only.
634
+ *
635
+ * Resolves with the decision beside the recorded one, so a test can show whether a code change
636
+ * alters a past outcome. A call the capture cannot answer stops the replay unless `facts`
637
+ * answers it; the result names the first one.
638
+ */
639
+ declare function replayAttempt<Q extends TestableQuest>(quest: Q, capture: unknown, options?: ReplayOptions): Promise<AttemptReplay>;
640
+
641
+ export { type AttemptReplay, type CalendarSegment, type CapabilityCall, type CapabilityOutcome, type CapabilityRequest, Decision, DecisionAssertionError, type FakeAnswer, type QuestHostContext, type QuestInputOf, type QuestRun, type ReplayDivergence, type ReplayOptions, type RunQuestOptions, type TestContext, type TestFacts, type TestRelease, TestSetupError, type TestableQuest, type TrackerFacts, type TrackerObservationInput, type TrackerReadRequest, type TrackerRecordInput, type WalletBalanceRequest, createTestContext, defaultMember, defaultNow, defaultSeed, expectAccept, expectDefer, expectProgress, expectReject, expectReview, replayAttempt, runQuest, trackerObservation, trackerPage };