@domino-sdk/relay 1.0.0-next.3 → 1.0.0-next.34

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 (61) hide show
  1. package/README.md +13 -1
  2. package/build.mjs +18 -1
  3. package/dist/activity-B8k9Sa_a.d.ts +9112 -0
  4. package/dist/authoring.d.ts +1347 -189
  5. package/dist/authoring.js +658 -226
  6. package/dist/automatic-outcomes-B1xrETxm.d.ts +758 -0
  7. package/dist/avatar.d.ts +29 -0
  8. package/dist/avatar.js +21 -0
  9. package/dist/browser-J7tUpXxy.d.ts +4154 -0
  10. package/dist/browser.d.ts +11 -4580
  11. package/dist/browser.js +8 -6
  12. package/dist/capability-error-DNMwKmlL.d.ts +458 -0
  13. package/dist/chunk-36HTX2BM.js +1223 -0
  14. package/dist/chunk-6QJ3LADK.js +112 -0
  15. package/dist/chunk-BGGKNIRP.js +171 -0
  16. package/dist/chunk-EYH5RDIE.js +496 -0
  17. package/dist/chunk-GQKYAQM6.js +84 -0
  18. package/dist/chunk-GUP7YRR4.js +42 -0
  19. package/dist/chunk-GZ6FJAXN.js +1659 -0
  20. package/dist/chunk-JON5SESL.js +2986 -0
  21. package/dist/chunk-MC6V6VMG.js +49 -0
  22. package/dist/chunk-NPGENI7K.js +37 -0
  23. package/dist/chunk-V7UKZLHA.js +35 -0
  24. package/dist/chunk-VFHHLN6A.js +284 -0
  25. package/dist/chunk-WJSSJ7AF.js +151 -0
  26. package/dist/{chunk-VH4OQ5VX.js → chunk-XFMSUPNS.js} +26 -5
  27. package/dist/{chunk-FDWRBMB3.js → chunk-ZVIRG24J.js} +150 -33
  28. package/dist/client-XiuFnug_.d.ts +4262 -0
  29. package/dist/groups-Ck-OxzjD.d.ts +2449 -0
  30. package/dist/identity-integration-GxAHdKR2.d.ts +58 -0
  31. package/dist/images-Dv-P5VBw.d.ts +234 -0
  32. package/dist/index.d.ts +15 -13115
  33. package/dist/index.js +30 -689
  34. package/dist/internal.d.ts +159 -0
  35. package/dist/internal.js +79 -0
  36. package/dist/offers-Cy-e4o5x.d.ts +431 -0
  37. package/dist/outcomes-kVB-Juzs.d.ts +4902 -0
  38. package/dist/pages-BBYD21IE.d.ts +359 -0
  39. package/dist/participant-rewards-3duLb8YJ.d.ts +668 -0
  40. package/dist/portal-proxy.js +26 -9
  41. package/dist/profiles-D2aFcOxu.d.ts +297 -0
  42. package/dist/react/index.d.ts +3378 -3318
  43. package/dist/react/index.js +1635 -783
  44. package/dist/request-error-DWduJCGV.d.ts +62 -0
  45. package/dist/schema-DfJzH2ci.d.ts +5644 -0
  46. package/dist/schema.d.ts +15 -3388
  47. package/dist/schema.js +790 -3
  48. package/dist/server/index.d.ts +81498 -0
  49. package/dist/server/index.js +2520 -0
  50. package/dist/streaks-CWyq8Px5.d.ts +71 -0
  51. package/dist/submission-input-BZkm6ohU.d.ts +290 -0
  52. package/dist/units-CwgsPB_r.d.ts +9 -0
  53. package/dist/vite.d.ts +1 -1
  54. package/dist/vite.js +1 -0
  55. package/dist/wallet-YssWxGg8.d.ts +228 -0
  56. package/package.json +23 -4
  57. package/dist/chunk-4KNTMNXA.js +0 -1847
  58. package/dist/chunk-B76BAJ25.js +0 -624
  59. package/dist/chunk-NKGJEYZM.js +0 -1833
  60. package/dist/chunk-ONDBQSMU.js +0 -373
  61. package/dist/submission-input-jVvTh4Ed.d.ts +0 -4992
@@ -1,20 +1,474 @@
1
- import { A as AdmittedContent, O as Observation, T as TrackerTriggerContext, a as TrackerReader, X as XReader, I as ImageReader, D as DiscordMember, b as DiscordMessage, W as WalletConnection, S as SolanaBalance, L as LinkedWallet, c as WalletBalanceQuery, d as WalletBalance, e as TrackerDefinition, f as TrackerTriggerMode, g as TrackerWhere, o as observationTriggerSchema, h as TrackerTriggerPolicy, B as Budget, i as AuthoringIdentity, C as ContentMetric, j as IntegrationProvider, k as StreakPolicy, l as TextEvidence, U as UrlEvidence, m as TextOptions, n as UrlOptions } from './submission-input-jVvTh4Ed.js';
2
- export { E as EvmChainId, p as content, q as customSource, r as defineEngagementReward, s as defineLeaderboard, t as defineReferral, u as defineTracker, v as discord, w as formatUnits, x as isEvmChainId, y as parseUnits, z as perContent, F as pointLedgers, G as settings, H as streak, J as trackerTriggerContextSchema, K as x } from './submission-input-jVvTh4Ed.js';
1
+ import { cB as xContentBodySchema, I as IdentityKind, aM as customSourceSchema, at as WithRecordData, as as WithContent, ar as WithAccountRoles, cG as QuestHandle, cH as LedgerReference, cI as GroupHandle, cF as ResourceHandle, ad as TrackerSource, c1 as trackerDefinitionSchema, U as Tracker, $ as TrackerData, H as SourceRoles, cJ as LedgerHandle, cD as xSearchSourceSchema, av as XTweet, au as XContentMetric, aj as TrackerTriggerPolicy, ap as Where, r as MemberIdentity, ah as TrackerTriggerContext, ab as TrackerReader, L as TextReviewInput, J as TextResult, P as PhotoResult, n as Decision, by as rewardSchema, ai as TrackerTriggerMode, F as RoleOf, aq as WhereSetting, k as ContentBody, l as ContentMetricName, cw as triggerSchema, d as QuestPresentation, e as QuestProfile, f as QuizEvidence, N as TieredRewardDefinition } from './schema-DfJzH2ci.js';
2
+ export { cK as LedgerSetting, a1 as TrackerDataSchema, a6 as TrackerPage, aa as TrackerReadQuery, cL as trackerDataSchema, cn as trackerTriggerContextSchema } from './schema-DfJzH2ci.js';
3
3
  import { z } from 'zod';
4
- import { TextReviewInput, TextResult, PhotoResult, rewardSchema, triggerSchema, QuestPresentation, QuestProfile, QuizEvidence, Decision, TieredRewardDefinition } from './schema.js';
4
+ export { z } from 'zod';
5
+ import { E as EngagementBudget, a4 as leaderboardDefinitionSchema, aQ as AuthoringIdentity, au as pointLedgerDeclarationSchema, aJ as referralAuthoringSchema, C as CampaignDefinition, A as AvailabilityWindow } from './groups-Ck-OxzjD.js';
6
+ export { G as defineCampaign, H as defineGroup } from './groups-Ck-OxzjD.js';
7
+ import { u as discordMessagesSourceSchema, e as DiscordMessageData, f as DiscordMessageTextData, w as discordReactionsSourceSchema, g as DiscordReactionData, h as DiscordReader, P as Prerequisite, T as TextEvidence, U as UrlEvidence, b as TextOptions, c as UrlOptions } from './submission-input-BZkm6ohU.js';
8
+ export { k as balanceAtLeast, m as completed, B as inGroup } from './submission-input-BZkm6ohU.js';
9
+ import { Q as QuizContent, a as StreakPolicy } from './streaks-CWyq8Px5.js';
10
+ import { d as ResourceSource, S as Setting, b as IntegrationModule, i as XReader, B as Budget, I as IntegerSettings } from './capability-error-DNMwKmlL.js';
11
+ export { L as CapabilityError, C as CapabilityErrorCode, k as capabilityErrorCodes } from './capability-error-DNMwKmlL.js';
12
+ import { e as ImageReader } from './images-Dv-P5VBw.js';
13
+ export { e as defineOffer } from './offers-Cy-e4o5x.js';
14
+ import { l as WalletReader } from './wallet-YssWxGg8.js';
15
+ export { h as CosmosDenom, a as CosmosNetwork, E as EvmChainId, j as WalletBalance, k as WalletBalanceQuery, p as cosmosDenomSchema, q as cosmosNetworkSchema, t as isEvmChainId } from './wallet-YssWxGg8.js';
16
+ export { f as formatUnits, p as parseUnits } from './units-CwgsPB_r.js';
17
+
18
+ declare function defineLedger(input: z.input<typeof pointLedgerDeclarationSchema>): {
19
+ name: string;
20
+ description: string;
21
+ key: string;
22
+ } & ResourceHandle<"ledger">;
23
+ /** One independent cumulative formula; management changes capture a new scoring boundary. */
24
+ declare function defineEngagementReward<const M extends readonly [string, ...string[]]>(input: {
25
+ key: string;
26
+ qualifiedBy: QuestHandle;
27
+ ledger: LedgerReference;
28
+ metrics: M;
29
+ baseline: "historical";
30
+ maxAgeMs?: number;
31
+ budgets?: EngagementBudget[];
32
+ target: (input: {
33
+ metrics: Record<M[number], number>;
34
+ }) => number;
35
+ }): {
36
+ key: string;
37
+ describe: () => {
38
+ key: string;
39
+ qualifiedBy: string;
40
+ balance: string;
41
+ metrics: string[];
42
+ baseline: "historical";
43
+ maxAgeMs: number;
44
+ budgets: {
45
+ scope: "member" | "project";
46
+ period: "lifetime" | "day" | "week" | "month";
47
+ limit: number;
48
+ }[];
49
+ };
50
+ score(raw: unknown): {
51
+ target: number;
52
+ baseline: number;
53
+ };
54
+ };
55
+ /**
56
+ * One milestone per quest, after `days` consecutive project calendar days with an accepted
57
+ * attempt. Multiple accepted attempts occupy one day. The day comes from the attempt's trusted
58
+ * occurrence time: a tracker record's `occurredAt` for `automatic({ tracker })`, and the
59
+ * submission's admission time for `manual()`, so a manual streak counts the days a member
60
+ * submitted. Days begin at midnight in the project timezone (`calendar.timeZone` in relay.json, or
61
+ * Console settings). Not available on content quests or prerequisite-only `automatic()`.
62
+ */
63
+ declare const streak: (options: {
64
+ days: number;
65
+ }) => StreakPolicy;
66
+ /** The number of distinct qualifying actions in one counter achievement. */
67
+ declare const count: (count: number) => {
68
+ kind: "count";
69
+ count: number;
70
+ } & z.core.$brand<"counter-goal">;
71
+ /** A counter window in the shared project calendar, with a bounded lateness allowance. */
72
+ declare const calendar: (period: "day" | "week" | "month", options?: {
73
+ latenessMs?: number;
74
+ }) => ({
75
+ kind: "lifetime";
76
+ } & z.core.$brand<"counter-window">) | ({
77
+ kind: "calendar";
78
+ period: "day" | "week" | "month";
79
+ latenessMs: number;
80
+ } & z.core.$brand<"counter-window">) | ({
81
+ kind: "rolling";
82
+ durationMs: number;
83
+ } & z.core.$brand<"counter-window">);
84
+ /** A trailing elapsed-time window, independent of timezone and calendar boundaries. */
85
+ declare const rolling: ({ days }: {
86
+ days: number;
87
+ }) => ({
88
+ kind: "lifetime";
89
+ } & z.core.$brand<"counter-window">) | ({
90
+ kind: "calendar";
91
+ period: "day" | "week" | "month";
92
+ latenessMs: number;
93
+ } & z.core.$brand<"counter-window">) | ({
94
+ kind: "rolling";
95
+ durationMs: number;
96
+ } & z.core.$brand<"counter-window">);
97
+ declare const questCompleted: (quest: QuestHandle) => {
98
+ kind: "quest";
99
+ quest: QuestHandle;
100
+ };
101
+ type ReferralInput = z.input<typeof referralAuthoringSchema>;
102
+ type ReferralBonus = NonNullable<ReferralInput["bonuses"]>[number];
103
+ type ReferralMilestone = NonNullable<ReferralInput["milestones"]>[number];
104
+ declare function defineReferral(input: Omit<ReferralInput, "qualification" | "inviterGroup" | "milestones" | "bonuses"> & {
105
+ qualification: {
106
+ kind: "signup" | "external";
107
+ } | ReturnType<typeof questCompleted>;
108
+ inviterGroup?: GroupHandle;
109
+ milestones?: (Omit<ReferralMilestone, "id"> & {
110
+ key: string;
111
+ })[];
112
+ bonuses?: (Omit<ReferralBonus, "id" | "balance" | "quests"> & {
113
+ key: string;
114
+ ledger: LedgerReference;
115
+ quests?: QuestHandle[];
116
+ })[];
117
+ }): {
118
+ title: string;
119
+ rewards: {
120
+ inviter: ({
121
+ kind: "tier";
122
+ reward: {
123
+ id: string;
124
+ title: string;
125
+ tiers: {
126
+ id: string;
127
+ title: string;
128
+ }[];
129
+ inventory: {
130
+ kind: "untracked";
131
+ };
132
+ fulfillment: {
133
+ kind: "staff-handover";
134
+ } | {
135
+ kind: "automatic";
136
+ };
137
+ };
138
+ tier: string;
139
+ } | {
140
+ kind: "points";
141
+ balance: string;
142
+ amount: number;
143
+ })[];
144
+ invitee: ({
145
+ kind: "tier";
146
+ reward: {
147
+ id: string;
148
+ title: string;
149
+ tiers: {
150
+ id: string;
151
+ title: string;
152
+ }[];
153
+ inventory: {
154
+ kind: "untracked";
155
+ };
156
+ fulfillment: {
157
+ kind: "staff-handover";
158
+ } | {
159
+ kind: "automatic";
160
+ };
161
+ };
162
+ tier: string;
163
+ } | {
164
+ kind: "points";
165
+ balance: string;
166
+ amount: number;
167
+ })[];
168
+ };
169
+ qualification: {
170
+ kind: "signup";
171
+ } | {
172
+ kind: "quest";
173
+ quest: string;
174
+ } | {
175
+ kind: "external";
176
+ };
177
+ enabled: boolean;
178
+ milestones: {
179
+ id: string;
180
+ count: number;
181
+ rewards: ({
182
+ kind: "tier";
183
+ reward: {
184
+ id: string;
185
+ title: string;
186
+ tiers: {
187
+ id: string;
188
+ title: string;
189
+ }[];
190
+ inventory: {
191
+ kind: "untracked";
192
+ };
193
+ fulfillment: {
194
+ kind: "staff-handover";
195
+ } | {
196
+ kind: "automatic";
197
+ };
198
+ };
199
+ tier: string;
200
+ } | {
201
+ kind: "points";
202
+ balance: string;
203
+ amount: number;
204
+ })[];
205
+ }[];
206
+ bonuses: {
207
+ id: string;
208
+ balance: string;
209
+ basisPoints: number;
210
+ external: boolean;
211
+ quests?: string[] | undefined;
212
+ durationDays?: number | undefined;
213
+ maxPoints?: number | undefined;
214
+ }[];
215
+ key: string;
216
+ inviterGroup?: string | undefined;
217
+ } & ResourceHandle<"referral">;
218
+ type LeaderboardInput = z.input<typeof leaderboardDefinitionSchema>;
219
+ type EarnedScore = Extract<NonNullable<LeaderboardInput["score"]>, {
220
+ kind: "earned";
221
+ }>;
222
+ declare function earned(options?: Omit<EarnedScore, "kind" | "quests"> & {
223
+ quests?: QuestHandle[];
224
+ }): {
225
+ window?: {
226
+ kind: "fixed";
227
+ start: number;
228
+ end: number;
229
+ } | {
230
+ kind: "all-time";
231
+ } | {
232
+ kind: "rolling";
233
+ days: number;
234
+ } | {
235
+ kind: "calendar";
236
+ period: "day" | "week" | "month";
237
+ } | undefined;
238
+ quests?: QuestHandle[];
239
+ kind: "earned";
240
+ };
241
+ declare function defineLeaderboard(input: Omit<LeaderboardInput, "key" | "id" | "balance" | "group" | "score"> & AuthoringIdentity & {
242
+ ledger: LedgerReference;
243
+ group?: GroupHandle;
244
+ score?: Exclude<LeaderboardInput["score"], {
245
+ kind: "earned";
246
+ }> | ReturnType<typeof earned>;
247
+ }): {
248
+ title: string;
249
+ balance: string;
250
+ access: "participants" | "public";
251
+ score: {
252
+ kind: "balance";
253
+ } | {
254
+ window: {
255
+ kind: "fixed";
256
+ start: number;
257
+ end: number;
258
+ } | {
259
+ kind: "all-time";
260
+ } | {
261
+ kind: "rolling";
262
+ days: number;
263
+ } | {
264
+ kind: "calendar";
265
+ period: "day" | "week" | "month";
266
+ };
267
+ kind: "earned";
268
+ quests?: string[] | undefined;
269
+ } | {
270
+ kind: "net";
271
+ window: {
272
+ kind: "fixed";
273
+ start: number;
274
+ end: number;
275
+ } | {
276
+ kind: "all-time";
277
+ } | {
278
+ kind: "rolling";
279
+ days: number;
280
+ } | {
281
+ kind: "calendar";
282
+ period: "day" | "week" | "month";
283
+ };
284
+ };
285
+ key: string;
286
+ settle?: {
287
+ at: "window-end";
288
+ ties: "shared" | "earliest";
289
+ prizes: {
290
+ ranks: [number, number];
291
+ rewards: ({
292
+ kind: "tier";
293
+ reward: {
294
+ id: string;
295
+ title: string;
296
+ tiers: {
297
+ id: string;
298
+ title: string;
299
+ }[];
300
+ inventory: {
301
+ kind: "untracked";
302
+ };
303
+ fulfillment: {
304
+ kind: "staff-handover";
305
+ } | {
306
+ kind: "automatic";
307
+ };
308
+ };
309
+ tier: string;
310
+ } | {
311
+ kind: "points";
312
+ balance: string;
313
+ amount: number;
314
+ })[];
315
+ }[];
316
+ } | undefined;
317
+ group?: string | undefined;
318
+ } & ResourceHandle<"leaderboard">;
319
+ /** An X post's body as content quests read it in `ctx.tracker.content.body`. */
320
+ type XContentBody = z.infer<typeof xContentBodySchema>;
321
+ declare const x: {
322
+ provider: "x";
323
+ /**
324
+ * Posts matching an X search. Each record's `data` is the provider's post payload. Its content
325
+ * is the post's normalized body (`XContentBody`), measured by the six X counters, so `content()`
326
+ * quests can use it.
327
+ */
328
+ search: (input: {
329
+ query: string;
330
+ }) => z.output<typeof xSearchSourceSchema> & WithRecordData<XTweet> & WithContent<XContentBody, XContentMetric>;
331
+ };
332
+ /**
333
+ * Records your own code sends with `trackers.ingest`. `data` is a zod object schema that every
334
+ * record's `data` must match: Relay stores its JSON Schema form with the tracker and rejects
335
+ * records that do not match it, and quests read each record's data with its type. With
336
+ * `identities`, each record's author, and each named account in `accounts`, is a verified identity
337
+ * of one of those kinds, which Relay attributes to the member who verified it, so quests can
338
+ * trigger from the tracker. A record states each account's `kind` unless the source names exactly
339
+ * one.
340
+ */
341
+ /** What a content source's records carry in `data`: the body, and the metrics each sample measures. */
342
+ type ContentData<B, M extends string> = {
343
+ body: B;
344
+ metrics?: Partial<Record<M, number>>;
345
+ };
346
+ /**
347
+ * Content your own code collects, such as posts from another platform: each record's `data` is
348
+ * `{ body, metrics? }`, where `body` matches the `body` schema and `metrics` holds the declared
349
+ * counters a sample measured (a counter a sample leaves out is unknown, never zero). The record's
350
+ * `author` is the creator, `occurredAt` the publication time, and its ID the content item. Quests
351
+ * use the tracker with `content()`, and a performance stage or engagement reward reads the
352
+ * declared metrics.
353
+ */
354
+ declare function customSource<B extends z.ZodObject, const M extends readonly string[] = [], const A extends readonly string[] = []>(namespace: string, options: {
355
+ identities?: IdentityKind[];
356
+ accounts?: A;
357
+ content: {
358
+ body: B;
359
+ metrics?: M;
360
+ };
361
+ }): z.output<typeof customSourceSchema> & WithRecordData<ContentData<z.input<B>, M[number]>> & WithContent<z.input<B>, M[number]> & WithAccountRoles<"author" | A[number]>;
362
+ declare function customSource<S extends z.ZodObject, const A extends readonly string[] = []>(namespace: string, options: {
363
+ identities?: IdentityKind[];
364
+ accounts?: A;
365
+ data: S;
366
+ }): z.output<typeof customSourceSchema> & WithRecordData<z.input<S>> & WithAccountRoles<"author" | A[number]>;
367
+ /** The content marker of a source, carried by the tracker built from it. */
368
+ type ContentOf<S> = S extends WithContent<infer B, infer M> ? WithContent<B, M> : unknown;
369
+ declare function defineTracker<S extends TrackerSource>(input: Omit<z.input<typeof trackerDefinitionSchema>, "source"> & {
370
+ source: S;
371
+ }): Tracker<TrackerData<S>> & ContentOf<S> & WithAccountRoles<SourceRoles<S>>;
372
+ type ChannelTypes = Extract<ResourceSource, {
373
+ resource: "channel";
374
+ }>["types"];
375
+ type DiscordMessagesSource = z.output<typeof discordMessagesSourceSchema>;
376
+ /**
377
+ * Messages members post in the project's Discord server. The Discord gateway writes one record per
378
+ * message, keyed by the message ID: its `author` is the poster's Discord account, `occurredAt` is
379
+ * when the message arrived, and `data` holds the channel, the replied-to message and the post time.
380
+ * A record is stored only when its author has linked that Discord account in the project, and its
381
+ * text only with `text: true`. Edits update stored text. Deleting a message, or publishing this
382
+ * tracker without `text: true`, removes retained text.
383
+ */
384
+ declare function messages(options?: {
385
+ text?: false;
386
+ }): DiscordMessagesSource & WithRecordData<DiscordMessageData>;
387
+ declare function messages(options: {
388
+ text: true;
389
+ }): DiscordMessagesSource & WithRecordData<DiscordMessageTextData>;
390
+ /**
391
+ * Reactions members add in the project's Discord server. The Discord gateway writes one record per
392
+ * reaction, keyed by message, reactor and emoji: its `author` is the reactor's Discord account and
393
+ * its `messageAuthor` account the message's author, when Discord names it. `occurredAt` is when
394
+ * the reaction arrived. A record is stored only when the reactor or the message author has linked
395
+ * that Discord account in the project. Pay the message author with
396
+ * `automatic({ tracker, beneficiary: "messageAuthor" })`; reactions to one's own message are
397
+ * skipped.
398
+ */
399
+ declare function reactions(): z.output<typeof discordReactionsSourceSchema> & WithRecordData<DiscordReactionData>;
400
+ declare const discord: {
401
+ provider: "discord";
402
+ grantRole: (roleId: string) => {
403
+ kind: "integration";
404
+ provider: "discord";
405
+ action: "grant-role";
406
+ roleId: string;
407
+ };
408
+ messages: typeof messages;
409
+ reactions: typeof reactions;
410
+ roles(options?: {
411
+ assignable?: boolean;
412
+ }): ResourceSource;
413
+ channels(options?: {
414
+ types?: ChannelTypes;
415
+ }): ResourceSource;
416
+ };
417
+ declare const pointLedgers: () => ResourceSource;
418
+ type Label = {
419
+ label: string;
420
+ description?: string;
421
+ };
422
+ declare const settings: {
423
+ pointLedger(options: Label & {
424
+ default?: LedgerHandle;
425
+ }): Setting<"point-ledger", z.ZodPrefault<z.core.$ZodBranded<z.ZodUnion<[z.ZodString, z.ZodLiteral<"">]>, "ledger-reference", "out">>>;
426
+ datetime(options: Label & {
427
+ default: string;
428
+ }): Setting<"datetime", z.ZodDefault<z.ZodPipe<z.ZodISODateTime, z.ZodTransform<string, string>>>>;
429
+ resource(options: Label & {
430
+ source: ResourceSource;
431
+ default?: string;
432
+ }): Setting<"resource", z.ZodDefault<z.ZodUnion<readonly [z.ZodLiteral<"">, z.ZodString]>>>;
433
+ quiz(options: Label & {
434
+ default: QuizContent;
435
+ }): Setting<"quiz", z.ZodDefault<z.ZodArray<z.ZodObject<{
436
+ id: z.ZodString;
437
+ prompt: z.ZodString;
438
+ choices: z.ZodArray<z.ZodObject<{
439
+ id: z.ZodString;
440
+ label: z.ZodString;
441
+ }, z.core.$strict>>;
442
+ correct: z.ZodString;
443
+ }, z.core.$strict>>>>;
444
+ text(options: Label & {
445
+ default: string;
446
+ minLength?: number;
447
+ maxLength?: number;
448
+ multiline?: boolean;
449
+ }): Setting<"text", z.ZodDefault<z.ZodString>>;
450
+ integer(options: Label & {
451
+ default: number;
452
+ min: number;
453
+ max: number;
454
+ }): Setting<"integer", z.ZodDefault<z.ZodNumber>>;
455
+ boolean(options: Label & {
456
+ default: boolean;
457
+ }): Setting<"boolean", z.ZodDefault<z.ZodBoolean>>;
458
+ choice<const T extends readonly [string, ...string[]]>(options: Label & {
459
+ options: T;
460
+ default: T[number];
461
+ }): Setting<"choice", z.ZodDefault<z.ZodEnum<{ [k_1 in T[number]]: k_1; } extends infer T_1 ? { [k in keyof T_1]: T_1[k]; } : never>>>;
462
+ /** A quest's settings: every field is built with one of the builders above. */
463
+ object<T extends Record<string, Setting>>(shape: T): z.ZodObject<{ -readonly [P in keyof T]: T[P]; }, z.core.$strict>;
464
+ };
5
465
 
6
466
  type Reward = z.infer<typeof rewardSchema>;
7
- declare const points: (balance: string, amount: number) => {
467
+ declare const points: (ledger: LedgerReference, amount: number) => {
8
468
  kind: "points";
9
469
  balance: string;
10
470
  amount: number;
11
471
  };
12
- declare const discordRole: (roleId: string) => {
13
- kind: "integration";
14
- provider: "discord";
15
- action: "grant-role";
16
- roleId: string;
17
- };
18
472
 
19
473
  declare const evidence: {
20
474
  text: (options?: TextOptions) => {
@@ -58,81 +512,209 @@ declare function manual(options: {
58
512
  input: "none";
59
513
  actor: "staff";
60
514
  };
515
+ /**
516
+ * Which members' activity a tracker trigger counts, and from when. With `enrollment: "required"`,
517
+ * a member's activity counts only once they enroll (`relay.quests.enroll`, or
518
+ * `management.quests.enroll` from a server), and `since` can also be `"enrollment"`.
519
+ */
520
+ type TriggerAdmission = {
521
+ /** `"none"` (the default): every member who has joined the project. */
522
+ enrollment?: "none";
523
+ /**
524
+ * The earliest activity counted: `"activation"` (the default), records since the quest was
525
+ * published; `"window"`, every record in the tracker's window.
526
+ */
527
+ since?: "activation" | "window";
528
+ } | {
529
+ /** Members enroll in the quest before their activity counts. */
530
+ enrollment: "required";
531
+ /**
532
+ * The earliest activity counted: `"activation"` (the default), `"window"`, or
533
+ * `"enrollment"`, records since the member enrolled. With `"activation"` or `"window"`, a
534
+ * record from before the member enrolled is historical.
535
+ */
536
+ since?: "activation" | "window" | "enrollment";
537
+ };
61
538
  /** A tracker trigger: which observations of which tracker run the quest, and for whom. */
62
- type TrackerTriggerInput = {
63
- tracker: TrackerDefinition;
539
+ type TrackerTriggerInput<T extends Tracker = Tracker, W extends Where<TrackerData<T>> | undefined = Where<TrackerData<T>> | undefined> = TriggerAdmission & {
540
+ /** The tracker handle `defineTracker` returns. */
541
+ tracker: T;
64
542
  /**
65
543
  * Which observations fire. `"new-record"`: each record's first observation (the default for X
66
- * trackers, where it means each newly collected post). `"new-observation"`: each observation
67
- * that becomes its record's current one (the default for custom trackers). `"data-changed"`: a
544
+ * and Discord trackers, where it means each newly collected post, message or reaction).
545
+ * `"new-observation"`: each observation that becomes its record's current one (the default for
546
+ * custom trackers). `"data-changed"`: a
68
547
  * new record, or a current observation whose `data` differs from the previous one.
69
548
  */
70
549
  on?: TrackerTriggerMode;
71
550
  /**
72
551
  * Admit only observations whose `data` matches, such as `{ path: "amount", gte: 1000 }` or
73
- * `{ path: "amount", gte: { setting: "threshold" } }`. Others record no outcome.
552
+ * `{ path: "amount", gte: { setting: "threshold" } }`, or a list of at most 10 such conditions
553
+ * that must all hold. Paths and values are checked against the tracker's data type, and a
554
+ * `setting` must name one of the quest's integer settings. Others record no outcome.
74
555
  */
75
- where?: TrackerWhere;
556
+ where?: W;
76
557
  /**
77
558
  * The record account whose member the quest pays: `"author"` (the default), `"inReplyTo"` on
78
- * an X tracker, or a named account a custom source declares in `accounts`. Skipped when that
79
- * account is the record's author account or belongs to the author's member.
559
+ * an X tracker, `"messageAuthor"` on a Discord reactions tracker, or a named account a custom
560
+ * source declares in `accounts`. Skipped when that account is the record's author account or
561
+ * belongs to the author's member, such as a reaction to one's own message.
562
+ */
563
+ beneficiary?: RoleOf<T>;
564
+ /**
565
+ * Who releases historical activity: a record that occurred before the member linked the
566
+ * account it pays (an unknown link time counts as before), or before they enrolled. `"staff"`
567
+ * (the default): only a reviewer's retry. `"claim"`: also the member, with
568
+ * `relay.quests.claim`. `"automatic"`: Relay admits it, including when the member links the
569
+ * account or enrolls later. Accounts of kind `member` are never historical.
80
570
  */
81
- beneficiary?: string;
571
+ historical?: "staff" | "claim" | "automatic";
82
572
  };
573
+ /** Type-only markers a tracker trigger carries into `defineQuest`. They never exist at runtime. */
574
+ declare const triggerData: unique symbol;
575
+ declare const triggerSettings: unique symbol;
576
+ declare const triggerBody: unique symbol;
577
+ declare const triggerMetrics: unique symbol;
83
578
  /**
84
- * An automatic quest. With no argument it runs once its prerequisites are complete; with an
85
- * observation it runs for each matching observation; with a tracker it runs for each observation
86
- * its firing mode and filter admit, for the member Relay attributes the beneficiary account to.
579
+ * A tracker trigger whose records carry `data` of type `D` and whose filter compares with the
580
+ * settings `S`. On a content source, its content body has type `B` and its metrics are `M`.
581
+ * `defineQuest` types `ctx.tracker` from `D` and `B` and checks `S` against its integer settings.
87
582
  */
88
- declare function automatic(): {
583
+ type TrackerTrigger<D = unknown, S extends string = never, B = never, M extends string = never> = {
89
584
  kind: "automatic";
585
+ tracker: TrackerTriggerPolicy;
586
+ readonly [triggerData]?: D;
587
+ readonly [triggerSettings]?: S;
588
+ readonly [triggerBody]?: B;
589
+ readonly [triggerMetrics]?: M;
90
590
  };
91
- declare function automatic(observation: z.infer<typeof observationTriggerSchema>): {
92
- kind: "automatic";
93
- observation: z.infer<typeof observationTriggerSchema>;
591
+ /**
592
+ * A content quest's trigger: a tracker trigger on a content source with the content stage. It
593
+ * completes once per content item, so its quest takes no `completion`.
594
+ */
595
+ type ContentTrigger<D = unknown, S extends string = never, B = unknown, M extends string = string> = TrackerTrigger<D, S, B, M> & {
596
+ tracker: TrackerTriggerPolicy & {
597
+ content: true;
598
+ };
94
599
  };
95
- declare function automatic(input: TrackerTriggerInput): {
600
+ type TriggerData<G> = G extends {
601
+ readonly [triggerData]?: infer D;
602
+ } ? unknown extends D ? unknown : Exclude<D, undefined> : unknown;
603
+ type TriggerSettings<G> = G extends {
604
+ readonly [triggerSettings]?: infer S;
605
+ } ? unknown extends S ? never : Exclude<S, undefined> : never;
606
+ type TriggerBody<G> = G extends {
607
+ readonly [triggerBody]?: infer B;
608
+ } ? Exclude<B, undefined> : never;
609
+ /** The metric names a content trigger's source measures. */
610
+ type TriggerMetrics<G> = G extends {
611
+ readonly [triggerMetrics]?: infer M;
612
+ } ? Exclude<M, undefined> : never;
613
+ /** A trigger that runs a content stage. */
614
+ type IsContent<G> = G extends {
615
+ tracker: {
616
+ content: true;
617
+ };
618
+ } ? true : false;
619
+ /** A tracker's content body type, or never when its source declares no content. */
620
+ type BodyOf<T> = T extends WithContent<unknown, string> ? ContentBody<T> : never;
621
+ /**
622
+ * An automatic quest. With no argument it runs once its prerequisites are complete; with a tracker
623
+ * it runs for each observation its firing mode and filter admit, for the member Relay attributes
624
+ * the beneficiary account to.
625
+ */
626
+ declare function automatic(): {
96
627
  kind: "automatic";
97
- tracker: TrackerTriggerPolicy;
98
628
  };
99
- declare const budget: (definition: Budget) => {
100
- id: string;
101
- scope: "member" | "project";
102
- period: "lifetime" | "day" | "week";
103
- limit: number;
104
- cost: number | {
105
- balance: string;
106
- };
629
+ declare function automatic<T extends Tracker, const W extends Where<TrackerData<T>> | undefined = undefined>(input: TrackerTriggerInput<T, W>): TrackerTrigger<TrackerData<T>, WhereSetting<W>, BodyOf<T>>;
630
+ /** A content quest's trigger: which content items of which tracker it takes, and from whom. */
631
+ type ContentTriggerInput<T extends Tracker = Tracker, W extends Where<TrackerData<T>> | undefined = Where<TrackerData<T>> | undefined> = TriggerAdmission & {
632
+ /** A tracker handle from `defineTracker` whose source has content. */
633
+ tracker: T;
634
+ /** Take only content items whose first observation's `data` matches. */
635
+ where?: W;
636
+ /**
637
+ * Who releases historical content: posts from before the creator linked the account or
638
+ * enrolled. `"claim"` (the default): the creator claims it with `relay.quests.claim`. `"staff"`:
639
+ * only a reviewer's retry. `"automatic"`: Relay takes it.
640
+ */
641
+ historical?: "staff" | "claim" | "automatic";
107
642
  };
108
- declare const keyed: (key: (ctx: {
643
+ /**
644
+ * A content quest: each content item a tracker collects, such as an X post or a custom source's
645
+ * record, becomes one attempt for its author's member, decided once on its first observation and
646
+ * evaluated again when its body changes. Completes once per content item: the quest takes no
647
+ * `completion`. With `performance`, a later observation's metrics gate the rewards.
648
+ */
649
+ declare function content<T extends Tracker & WithContent<unknown, string>, const W extends Where<TrackerData<T>> | undefined = undefined>(input: ContentTriggerInput<T, W>): ContentTrigger<TrackerData<T>, WhereSetting<W>, ContentBody<T>, ContentMetricName<T>>;
650
+ /**
651
+ * What a trigger `G` supplies under key `K`: `Present` when the trigger has it, null when it cannot,
652
+ * and `Present | null` when `G` is not known.
653
+ */
654
+ type Supplied<G, K extends string, Present, Base> = unknown extends G ? Base | null : G extends unknown ? K extends keyof G ? [G[K]] extends [object] ? Present : Base | null : null : never;
655
+ /**
656
+ * `ctx.tracker` for a trigger: non-null and typed for a tracker trigger, null for others. On a
657
+ * content source, `content.body` has the source's body type.
658
+ */
659
+ type ContextTracker<G> = Supplied<G, "tracker", TrackerTriggerContext<TriggerData<G>, TriggerBody<G>>, TrackerTriggerContext>;
660
+ /**
661
+ * What a `keyed()` completion key reads. TypeScript cannot carry the trigger into a completion
662
+ * built inline, so `tracker` stays nullable here; the evaluator's `ctx.tracker` is typed.
663
+ */
664
+ type KeyedContext = {
109
665
  member: {
110
666
  id: string;
111
667
  };
112
- content?: AdmittedContent | null;
113
- observation: Observation | null;
114
- /** The pinned tracker observation of a tracker-triggered quest. */
115
- tracker?: TrackerTriggerContext | null;
668
+ /** The pinned tracker observation of a tracker-triggered quest; null for other triggers. */
669
+ tracker: TrackerTriggerContext | null;
116
670
  eligibleAt: number;
671
+ /** The evaluation run's pinned project calendar. */
672
+ calendar: EvaluationCalendar;
117
673
  /** The attempt's evaluation time; see {@link EvaluationContext.now}. */
118
674
  now: number;
119
- }) => string) => {
675
+ };
676
+ declare const budget: (definition: Omit<Budget, "id" | "cost"> & {
677
+ key: string;
678
+ cost: number | {
679
+ ledger: LedgerReference;
680
+ };
681
+ }) => {
682
+ id: string;
683
+ scope: "member" | "project";
684
+ period: "lifetime" | "day" | "week" | "month";
685
+ limit: number;
686
+ cost: number | {
687
+ balance: string;
688
+ };
689
+ };
690
+ declare const keyed: (key: (ctx: KeyedContext) => string) => {
120
691
  kind: "keyed";
121
- key: (ctx: {
122
- member: {
123
- id: string;
124
- };
125
- content?: AdmittedContent | null;
126
- observation: Observation | null;
127
- /** The pinned tracker observation of a tracker-triggered quest. */
128
- tracker?: TrackerTriggerContext | null;
129
- eligibleAt: number;
130
- /** The attempt's evaluation time; see {@link EvaluationContext.now}. */
131
- now: number;
132
- }) => string;
692
+ key: (ctx: KeyedContext) => string;
133
693
  };
134
- declare const completed: (quest: AuthoringIdentity | string) => {
135
- quest: string;
694
+ /** Accepted evidence contributes once under its distinct key; Relay commits progress with rewards. */
695
+ declare const progress: (definition: {
696
+ distinct: (ctx: KeyedContext) => string;
697
+ goal: ReturnType<typeof count>;
698
+ window?: ReturnType<typeof calendar>;
699
+ repeat?: "once" | "repeat";
700
+ }) => {
701
+ distinct: (ctx: KeyedContext) => string;
702
+ kind: "progress";
703
+ goal: {
704
+ kind: "count";
705
+ count: number;
706
+ };
707
+ window: {
708
+ kind: "lifetime";
709
+ } | {
710
+ kind: "calendar";
711
+ period: "day" | "week" | "month";
712
+ latenessMs: number;
713
+ } | {
714
+ kind: "rolling";
715
+ durationMs: number;
716
+ };
717
+ repeat: "repeat" | "once";
136
718
  };
137
719
  declare const untracked: () => {
138
720
  kind: "untracked";
@@ -140,11 +722,17 @@ declare const untracked: () => {
140
722
  declare const staffHandover: () => {
141
723
  kind: "staff-handover";
142
724
  };
143
- declare function defineTieredReward(input: Omit<TieredRewardDefinition, "id"> & AuthoringIdentity): {
725
+ declare const automaticFulfillment: () => {
726
+ kind: "automatic";
727
+ };
728
+ declare function defineTieredReward<const T extends readonly {
144
729
  key: string;
145
- /** @deprecated Authoring key alias. Use key. */
146
- id: string;
147
- tier: (tier: string) => {
730
+ title: string;
731
+ }[]>(input: Omit<TieredRewardDefinition, "id" | "tiers"> & AuthoringIdentity & {
732
+ tiers: T;
733
+ }): {
734
+ key: string;
735
+ tier: (tier: T[number]["key"]) => {
148
736
  kind: "tier";
149
737
  reward: {
150
738
  id: string;
@@ -158,25 +746,23 @@ declare function defineTieredReward(input: Omit<TieredRewardDefinition, "id"> &
158
746
  };
159
747
  fulfillment: {
160
748
  kind: "staff-handover";
749
+ } | {
750
+ kind: "automatic";
161
751
  };
162
752
  };
163
753
  tier: string;
164
754
  };
165
- };
755
+ } & ResourceHandle<"tiered-reward">;
166
756
  declare const once: () => {
167
757
  kind: "once";
168
758
  };
169
- type Outcome = {
759
+ type Outcome = (Omit<Extract<Decision, {
170
760
  kind: "accept";
761
+ }>, "rewards"> & {
171
762
  rewards?: Reward[];
172
- } | {
173
- kind: "review";
174
- reason: string;
175
- rewards?: Reward[];
176
- } | {
177
- kind: "reject";
178
- reason: string;
179
- };
763
+ }) | Exclude<Decision, {
764
+ kind: "accept";
765
+ }>;
180
766
  /**
181
767
  * A performance evaluator's answer. It gates the rewards content evaluation already selected, so
182
768
  * it carries none: a `rewards` value fails the evaluation.
@@ -195,9 +781,11 @@ type PerformanceOutcome = {
195
781
  declare function accept(): {
196
782
  kind: "accept";
197
783
  };
198
- declare function accept(options: {
199
- rewards?: Reward[];
200
- }): Outcome;
784
+ declare function accept(options: Omit<Extract<Outcome, {
785
+ kind: "accept";
786
+ }>, "kind">): Extract<Outcome, {
787
+ kind: "accept";
788
+ }>;
201
789
  declare function review(options: {
202
790
  reason: string;
203
791
  rewards?: undefined;
@@ -205,12 +793,23 @@ declare function review(options: {
205
793
  kind: "review";
206
794
  reason: string;
207
795
  };
208
- declare function review(options: {
209
- reason: string;
210
- rewards?: Reward[];
211
- }): Outcome;
796
+ declare function review(options: Omit<Extract<Outcome, {
797
+ kind: "review";
798
+ }>, "kind">): Extract<Outcome, {
799
+ kind: "review";
800
+ }>;
212
801
  declare const decision: {
213
802
  accept: typeof accept;
803
+ defer: (options: Omit<Extract<Decision, {
804
+ kind: "defer";
805
+ }>, "kind">) => Extract<Decision, {
806
+ kind: "defer";
807
+ }>;
808
+ progress: (options: Omit<Extract<Decision, {
809
+ kind: "progress";
810
+ }>, "kind">) => Extract<Decision, {
811
+ kind: "progress";
812
+ }>;
214
813
  reject: (options: {
215
814
  reason: string;
216
815
  }) => {
@@ -219,35 +818,70 @@ declare const decision: {
219
818
  };
220
819
  review: typeof review;
221
820
  };
821
+ /** The member an attempt evaluates. */
822
+ type EvaluationMember = {
823
+ id: string;
824
+ /**
825
+ * The member's selected X and Discord accounts and their `app:<name>` identities in this
826
+ * project, pinned once per evaluation run at the first call: later links and unlinks do not change
827
+ * this evaluation. Null when the member has none. `ctx.wallet.list()` reads wallets.
828
+ */
829
+ identities(): Promise<MemberIdentity[] | null>;
830
+ };
831
+ /** One project-calendar day, with epoch-millisecond bounds. */
832
+ type EvaluationCalendarDay = {
833
+ /** The stable completion-key form, such as `2026-10-01@Europe/Budapest`. */
834
+ key: string;
835
+ /** The local ISO date in `timeZone`. */
836
+ date: string;
837
+ timeZone: string;
838
+ /** Inclusive epoch-millisecond boundary. */
839
+ start: number;
840
+ /** Exclusive epoch-millisecond boundary. */
841
+ end: number;
842
+ };
843
+ /** The project calendar pinned for one evaluation run. */
844
+ type EvaluationCalendar = {
845
+ /** The day containing `at`, or the activity's `eligibleAt` when omitted. */
846
+ day(at?: number): EvaluationCalendarDay;
847
+ };
848
+ /**
849
+ * What an evaluator reads. `G` is the quest's trigger: `tracker` and `content` are non-null for
850
+ * the trigger that supplies them and null otherwise. `G` defaults to `any`, which
851
+ * leaves them nullable and lets a shared evaluator, such as `evaluators.photo()`, fit every quest.
852
+ */
853
+ type IntegrationReaders<D extends readonly IntegrationModule[]> = Pick<{
854
+ x: XReader;
855
+ discord: DiscordReader;
856
+ }, D[number]["provider"]>;
222
857
  type EvaluationContext<T, I = {
223
858
  photo: string;
224
- }> = {
859
+ }, G = any, D extends readonly IntegrationModule[] = readonly IntegrationModule[]> = {
225
860
  settings: T;
226
- member: {
227
- id: string;
228
- };
861
+ member: EvaluationMember;
229
862
  input: I;
230
- content: AdmittedContent | null;
231
- observation: Observation | null;
232
863
  /**
233
864
  * The tracker observation that admitted this attempt, and the member and verified account it
234
- * was attributed to. Null unless the quest has a tracker trigger.
865
+ * was attributed to. Present for a tracker trigger, with `record.data` of the tracker's type.
866
+ * On a content source, `content` holds the body revision being evaluated, with the source's
867
+ * body type.
235
868
  */
236
- tracker: TrackerTriggerContext | null;
869
+ tracker: ContextTracker<G>;
237
870
  /**
238
- * When the activity happened, in epoch milliseconds: the observation's or tracker record's
239
- * occurrence time, else when the attempt was admitted. Budgets and daily keys use it.
871
+ * When the activity happened, in epoch milliseconds: the tracker record's occurrence time, else
872
+ * when the attempt was admitted. Budgets and daily keys use it.
240
873
  */
241
874
  eligibleAt: number;
875
+ /** The project calendar pinned when this evaluation run started. */
876
+ calendar: EvaluationCalendar;
242
877
  /**
243
- * The attempt's evaluation time, in epoch milliseconds: when its first evaluation started.
244
- * Every retry and replay of the attempt receives the same value, and the sandbox freezes
878
+ * The current evaluation run's start time in epoch milliseconds.
879
+ * Retries and replays of that run receive the same value; a scheduled defer starts a fresh run, and the sandbox freezes
245
880
  * `Date.now()` and `new Date()` at it. Use `eligibleAt` for when the activity
246
881
  * happened.
247
882
  */
248
883
  now: number;
249
884
  trackers: TrackerReader;
250
- x: XReader;
251
885
  images: ImageReader;
252
886
  review: {
253
887
  text(options: TextReviewInput): Promise<TextResult>;
@@ -256,31 +890,11 @@ type EvaluationContext<T, I = {
256
890
  criteria: string;
257
891
  }): Promise<PhotoResult>;
258
892
  };
259
- discord: {
260
- member(): Promise<DiscordMember | null>;
261
- message(input: {
262
- channelId: string;
263
- messageId: string;
264
- }): Promise<DiscordMessage | null>;
265
- };
266
- wallet: {
267
- /** The member's newest linked Solana wallet. */
268
- connection(): Promise<WalletConnection | null>;
269
- /** SOL held by the newest linked Solana wallet. */
270
- solanaBalance(): Promise<SolanaBalance | null>;
271
- /** Every wallet the member has linked to this project, pinned once per attempt. */
272
- list(): Promise<LinkedWallet[]>;
273
- /**
274
- * The native or token balance of the member's pinned linked wallets on one chain: all wallets of
275
- * that family, or `address` (which must be one of them). No wallets gives `total: "0"` and
276
- * `wallets: []`. Provider failures throw; they never read as a zero balance.
277
- */
278
- balance(query: WalletBalanceQuery): Promise<WalletBalance>;
279
- };
280
- };
893
+ wallet: WalletReader;
894
+ } & IntegrationReaders<D>;
281
895
  type Evaluator<T, I = {
282
896
  photo: string;
283
- }> = (ctx: EvaluationContext<T, I>) => Promise<Outcome>;
897
+ }, G = any, D extends readonly IntegrationModule[] = readonly []> = (ctx: EvaluationContext<T, I, G, D>) => Promise<Outcome>;
284
898
  declare const evaluators: {
285
899
  quiz(answerKey: QuizEvidence["answers"], options?: {
286
900
  minimumCorrect?: number;
@@ -304,21 +918,59 @@ type QuestInput<T extends Trigger> = T extends {
304
918
  } ? TextEvidence : T extends {
305
919
  input: "url";
306
920
  } ? UrlEvidence : Record<string, never>;
307
- declare function defineQuest<T extends Record<string, z.ZodType>, const G extends Trigger, const M extends readonly [ContentMetric, ...ContentMetric[]] = readonly [
308
- ContentMetric,
309
- ...ContentMetric[]
310
- ]>(definition: AuthoringIdentity & {
921
+ /**
922
+ * Rejects a trigger whose filter compares with settings that are not integer settings of the
923
+ * quest, naming them.
924
+ */
925
+ type IntegerSettingBounds<G, T> = [
926
+ Exclude<TriggerSettings<G>, IntegerSettings<T>>
927
+ ] extends [never] ? unknown : {
928
+ readonly "The tracker filter compares with settings that are not integer settings of this quest": Exclude<TriggerSettings<G>, IntegerSettings<T>>;
929
+ };
930
+ /** How a quest completes: a content quest once per content item, so it takes no `completion`. */
931
+ type CompletionFor<G> = IsContent<G> extends true ? {
932
+ /** A content quest completes once per content item; it takes no completion. */
933
+ completion?: never;
934
+ } : G extends {
935
+ kind: "automatic";
936
+ tracker?: never;
937
+ } ? {
938
+ completion: ReturnType<typeof once>;
939
+ } : {
940
+ completion: ReturnType<typeof once> | ReturnType<typeof keyed> | StreakPolicy | ReturnType<typeof progress>;
941
+ };
942
+ /** What a content quest's performance stage reads: the declared metrics it chose, fresh. */
943
+ type PerformanceContext<S, G, M extends string> = {
944
+ settings: S;
945
+ member: {
946
+ id: string;
947
+ };
948
+ /** The content item's pinned observation, attribution and body revision. */
949
+ tracker: ContextTracker<G>;
950
+ /** The chosen metrics of one complete, fresh sample. */
951
+ metrics: Record<M, number>;
952
+ /** When the sample was observed. */
953
+ observedAt: number;
954
+ };
955
+ /** A concrete quest: prerequisite-only automatic triggers need at least one prerequisite. */
956
+ declare const defineQuest: <T extends Record<string, Setting>, const G extends Trigger, const D extends readonly IntegrationModule[] = readonly [], const M extends readonly [string, ...string[]] = readonly [string, ...string[]]>(definition: AuthoringIdentity & CompletionFor<G> & (G extends {
957
+ kind: "automatic";
958
+ tracker?: never;
959
+ } ? {
960
+ requires: readonly [Prerequisite, ...Prerequisite[]];
961
+ } : unknown) & {
311
962
  title: string | ((ctx: {
312
- settings: z.output<z.ZodObject<T>>;
963
+ settings: z.core.$InferObjectOutput<T, {}>;
313
964
  }) => string);
314
- settings: z.ZodObject<T>;
315
- presentation?: (ctx: {
316
- settings: z.output<z.ZodObject<T>>;
317
- }) => QuestPresentation;
318
- trigger: G;
319
- integrations?: IntegrationProvider[];
320
- requires?: ReturnType<typeof completed>[];
321
- completion: ReturnType<typeof once> | ReturnType<typeof keyed> | StreakPolicy;
965
+ settings: z.ZodObject<T, z.core.$strip>;
966
+ presentation?: ((ctx: {
967
+ settings: z.core.$InferObjectOutput<T, {}>;
968
+ }) => QuestPresentation) | undefined;
969
+ trigger: G & NoInfer<IntegerSettingBounds<G, T>>;
970
+ integrations?: D | undefined;
971
+ requires?: readonly Prerequisite[];
972
+ campaign?: CampaignDefinition;
973
+ availability?: AvailabilityWindow;
322
974
  visibility?: "visible" | "hidden";
323
975
  /**
324
976
  * `{ visible: true }` lists the quest's completions on participant profiles
@@ -326,37 +978,65 @@ declare function defineQuest<T extends Record<string, z.ZodType>, const G extend
326
978
  */
327
979
  profile?: QuestProfile;
328
980
  budgets?: Budget[];
329
- review?: (ctx: {
330
- settings: z.output<z.ZodObject<T>>;
981
+ /**
982
+ * Whether staff can review this quest's attempts. Human review is on unless this returns
983
+ * `{ enabled: false }`. With it off, `decision.review(...)` becomes a reject that keeps the
984
+ * review reason, and the attempt records `requestedReview: true`; Console shows "Would have
985
+ * gone to review; human review is off".
986
+ */
987
+ review?: ((ctx: {
988
+ settings: z.core.$InferObjectOutput<T, {}>;
331
989
  }) => {
332
990
  enabled: boolean;
333
- };
334
- rewards: Reward[] | ((ctx: {
335
- settings: z.output<z.ZodObject<T>>;
336
- }) => Reward[]);
337
- evaluate?: Evaluator<z.output<z.ZodObject<T>>, QuestInput<G>>;
338
- performance?: G extends {
339
- content: unknown;
340
- } ? {
341
- metrics: M;
342
- maxAgeMs?: number;
343
- evaluate: (ctx: {
344
- settings: z.output<z.ZodObject<T>>;
345
- member: {
991
+ }) | undefined;
992
+ rewards: ({
993
+ kind: "tier";
994
+ reward: {
995
+ id: string;
996
+ title: string;
997
+ tiers: {
346
998
  id: string;
347
- };
348
- content: AdmittedContent;
349
- metrics: Record<M[number], number>;
350
- observedAt: number;
351
- }) => PerformanceOutcome | Promise<PerformanceOutcome>;
352
- } : never;
353
- }): {
999
+ title: string;
1000
+ }[];
1001
+ inventory: {
1002
+ kind: "untracked";
1003
+ };
1004
+ fulfillment: {
1005
+ kind: "staff-handover";
1006
+ } | {
1007
+ kind: "automatic";
1008
+ };
1009
+ };
1010
+ tier: string;
1011
+ } | {
1012
+ kind: "integration";
1013
+ provider: "discord";
1014
+ action: "grant-role";
1015
+ roleId: string;
1016
+ } | {
1017
+ kind: "points";
1018
+ balance: string;
1019
+ amount: number;
1020
+ })[] | ((ctx: {
1021
+ settings: z.core.$InferObjectOutput<T, {}>;
1022
+ }) => Reward[]);
1023
+ evaluate?: Evaluator<z.core.$InferObjectOutput<T, {}>, QuestInput<G>, NoInfer<G>, NoInfer<D>> | undefined;
1024
+ /**
1025
+ * A content quest's performance stage: once content evaluation accepts an item, each later
1026
+ * complete and fresh sample of `metrics` (a subset of the tracker's declared metrics) gates the
1027
+ * rewards it selected.
1028
+ */
1029
+ performance?: (IsContent<G> extends true ? {
1030
+ metrics: M & readonly TriggerMetrics<G>[];
1031
+ maxAgeMs?: number;
1032
+ evaluate: (ctx: PerformanceContext<z.core.$InferObjectOutput<T, {}>, G, M[number]>) => PerformanceOutcome | Promise<PerformanceOutcome>;
1033
+ } : never) | undefined;
1034
+ }) => {
1035
+ protocol: number;
354
1036
  key: string;
355
- /** @deprecated Authoring key alias. Use key. */
356
- id: string;
357
1037
  describe: (input: unknown) => {
358
1038
  quest: string;
359
- runtimeVersion: 1 | 2;
1039
+ evaluatorProtocol: 2;
360
1040
  title: string;
361
1041
  presentation: {
362
1042
  quiz?: {
@@ -378,7 +1058,7 @@ declare function defineQuest<T extends Record<string, z.ZodType>, const G extend
378
1058
  } | undefined;
379
1059
  } | undefined;
380
1060
  };
381
- integrations: "discord"[];
1061
+ integrations: ("discord" | "x")[];
382
1062
  fields: Record<string, {
383
1063
  kind: "point-ledger";
384
1064
  default: string;
@@ -393,9 +1073,6 @@ declare function defineQuest<T extends Record<string, z.ZodType>, const G extend
393
1073
  kind: "resource";
394
1074
  default: string;
395
1075
  source: {
396
- provider: "domino";
397
- resource: "point-ledger";
398
- } | {
399
1076
  provider: "discord";
400
1077
  resource: "channel";
401
1078
  types: ("text" | "announcement")[];
@@ -403,6 +1080,9 @@ declare function defineQuest<T extends Record<string, z.ZodType>, const G extend
403
1080
  provider: "discord";
404
1081
  resource: "role";
405
1082
  assignable: boolean;
1083
+ } | {
1084
+ provider: "domino";
1085
+ resource: "point-ledger";
406
1086
  };
407
1087
  label: string;
408
1088
  description?: string | undefined;
@@ -469,41 +1149,50 @@ declare function defineQuest<T extends Record<string, z.ZodType>, const G extend
469
1149
  };
470
1150
  fulfillment: {
471
1151
  kind: "staff-handover";
1152
+ } | {
1153
+ kind: "automatic";
472
1154
  };
473
1155
  };
474
1156
  tier: string;
475
- } | {
476
- kind: "points";
477
- balance: string;
478
- amount: number;
479
1157
  } | {
480
1158
  kind: "integration";
481
1159
  provider: "discord";
482
1160
  action: "grant-role";
483
1161
  roleId: string;
1162
+ } | {
1163
+ kind: "points";
1164
+ balance: string;
1165
+ amount: number;
484
1166
  })[];
485
1167
  humanReview: boolean;
486
1168
  trigger: {
1169
+ kind: "manual";
1170
+ input: "text";
1171
+ constraints: {
1172
+ required: boolean;
1173
+ minLength: number;
1174
+ maxLength: number;
1175
+ };
1176
+ actor?: "staff" | "member" | undefined;
1177
+ } | {
1178
+ kind: "manual";
1179
+ input: "url";
1180
+ constraints: {
1181
+ required: boolean;
1182
+ allowedHosts?: string[] | undefined;
1183
+ };
1184
+ actor?: "staff" | "member" | undefined;
1185
+ } | {
1186
+ kind: "manual";
1187
+ input: "none" | "quiz" | "photo";
1188
+ actor?: "staff" | "member" | undefined;
1189
+ } | {
487
1190
  kind: "automatic";
488
- observation?: {
489
- source: string;
490
- type: string;
491
- } | undefined;
492
- content?: {
493
- tracker: string;
494
- window: {
495
- start: number;
496
- end?: number | undefined;
497
- };
498
- enrollment: "required" | "none";
499
- posts: "after-enrollment" | "since-start";
500
- historical: "staff" | "automatic" | "claim";
501
- } | undefined;
502
1191
  tracker?: {
503
1192
  tracker: string;
504
- source: "custom" | "x-search";
1193
+ source: string;
1194
+ on: "new-record" | "new-observation" | "data-changed";
505
1195
  beneficiary: string;
506
- on?: "new-record" | "new-observation" | "data-changed" | undefined;
507
1196
  where?: {
508
1197
  path: string;
509
1198
  gt?: number | {
@@ -521,9 +1210,355 @@ declare function defineQuest<T extends Record<string, z.ZodType>, const G extend
521
1210
  } | {
522
1211
  path: string;
523
1212
  equals: string | number | boolean;
1213
+ } | ({
1214
+ path: string;
1215
+ gt?: number | {
1216
+ setting: string;
1217
+ } | undefined;
1218
+ gte?: number | {
1219
+ setting: string;
1220
+ } | undefined;
1221
+ lt?: number | {
1222
+ setting: string;
1223
+ } | undefined;
1224
+ lte?: number | {
1225
+ setting: string;
1226
+ } | undefined;
1227
+ } | {
1228
+ path: string;
1229
+ equals: string | number | boolean;
1230
+ })[] | undefined;
1231
+ enrollment?: "none" | "required" | undefined;
1232
+ since?: "activation" | "window" | "enrollment" | undefined;
1233
+ historical?: "staff" | "claim" | "automatic" | undefined;
1234
+ content?: true | undefined;
1235
+ } | undefined;
1236
+ };
1237
+ requires: ({
1238
+ kind: "completion";
1239
+ quest: string;
1240
+ scope: "ever";
1241
+ } | {
1242
+ kind: "completion";
1243
+ quest: string;
1244
+ scope: "period";
1245
+ period: "day" | "week" | "month";
1246
+ } | {
1247
+ kind: "balance";
1248
+ balance: string;
1249
+ minimum: number;
1250
+ } | {
1251
+ kind: "group";
1252
+ group: string;
1253
+ title: string;
1254
+ })[];
1255
+ completion: {
1256
+ kind: "progress";
1257
+ goal: {
1258
+ kind: "count";
1259
+ count: number;
1260
+ };
1261
+ window: {
1262
+ kind: "lifetime";
1263
+ } | {
1264
+ kind: "calendar";
1265
+ period: "day" | "week" | "month";
1266
+ latenessMs: number;
1267
+ } | {
1268
+ kind: "rolling";
1269
+ durationMs: number;
1270
+ };
1271
+ repeat: "repeat" | "once";
1272
+ } | {
1273
+ kind: "streak";
1274
+ days: number;
1275
+ } | {
1276
+ kind: "once";
1277
+ } | {
1278
+ kind: "keyed";
1279
+ };
1280
+ visibility: "visible" | "hidden";
1281
+ profile: {
1282
+ visible: boolean;
1283
+ };
1284
+ budgets: {
1285
+ id: string;
1286
+ scope: "member" | "project";
1287
+ period: "lifetime" | "day" | "week" | "month";
1288
+ limit: number;
1289
+ cost: number | {
1290
+ balance: string;
1291
+ };
1292
+ }[];
1293
+ performance?: {
1294
+ metrics: string[];
1295
+ maxAgeMs: number;
1296
+ } | undefined;
1297
+ campaign?: {
1298
+ key: string;
1299
+ title: string;
1300
+ enrollment: "none" | "required";
1301
+ window?: {
1302
+ from: number;
1303
+ until: number;
1304
+ } | undefined;
1305
+ } | undefined;
1306
+ availability?: {
1307
+ from: number;
1308
+ until: number;
1309
+ } | undefined;
1310
+ };
1311
+ evaluate(ctx: {
1312
+ settings: unknown;
1313
+ member: EvaluationMember;
1314
+ input: QuestInput<G>;
1315
+ /**
1316
+ * The tracker observation that admitted this attempt, and the member and verified account it
1317
+ * was attributed to. Present for a tracker trigger, with `record.data` of the tracker's type.
1318
+ * On a content source, `content` holds the body revision being evaluated, with the source's
1319
+ * body type.
1320
+ */
1321
+ tracker: TrackerTriggerContext | null;
1322
+ /**
1323
+ * When the activity happened, in epoch milliseconds: the tracker record's occurrence time, else
1324
+ * when the attempt was admitted. Budgets and daily keys use it.
1325
+ */
1326
+ eligibleAt: number;
1327
+ /** The project calendar pinned when this evaluation run started. */
1328
+ calendar: EvaluationCalendar;
1329
+ /**
1330
+ * The current evaluation run's start time in epoch milliseconds.
1331
+ * Retries and replays of that run receive the same value; a scheduled defer starts a fresh run, and the sandbox freezes
1332
+ * `Date.now()` and `new Date()` at it. Use `eligibleAt` for when the activity
1333
+ * happened.
1334
+ */
1335
+ now: number;
1336
+ trackers: TrackerReader;
1337
+ images: ImageReader;
1338
+ review: {
1339
+ text(options: TextReviewInput): Promise<TextResult>;
1340
+ photo(options: {
1341
+ image: string;
1342
+ criteria: string;
1343
+ }): Promise<PhotoResult>;
1344
+ };
1345
+ wallet: WalletReader;
1346
+ } & IntegrationReaders<readonly IntegrationModule[]> & {
1347
+ rewards: Reward[];
1348
+ humanReview: boolean;
1349
+ performance?: unknown;
1350
+ }): Promise<Decision>;
1351
+ } & ResourceHandle<"quest">;
1352
+ /** Publish this artifact as a reusable type. Its key names the type;
1353
+ * Console instances receive independent quest identities and pinned versions. */
1354
+ declare const defineQuestType: <T extends Record<string, Setting>, const G extends Trigger, const D extends readonly IntegrationModule[] = readonly [], const M extends readonly [string, ...string[]] = readonly [string, ...string[]]>(definition: AuthoringIdentity & CompletionFor<G> & {
1355
+ title: string | ((ctx: {
1356
+ settings: z.core.$InferObjectOutput<T, {}>;
1357
+ }) => string);
1358
+ settings: z.ZodObject<T, z.core.$strip>;
1359
+ presentation?: ((ctx: {
1360
+ settings: z.core.$InferObjectOutput<T, {}>;
1361
+ }) => QuestPresentation) | undefined;
1362
+ trigger: G & NoInfer<IntegerSettingBounds<G, T>>;
1363
+ integrations?: D | undefined;
1364
+ requires?: readonly Prerequisite[];
1365
+ campaign?: CampaignDefinition;
1366
+ availability?: AvailabilityWindow;
1367
+ visibility?: "visible" | "hidden";
1368
+ /**
1369
+ * `{ visible: true }` lists the quest's completions on participant profiles
1370
+ * (`relay.profiles.completions`). Hidden by default.
1371
+ */
1372
+ profile?: QuestProfile;
1373
+ budgets?: Budget[];
1374
+ /**
1375
+ * Whether staff can review this quest's attempts. Human review is on unless this returns
1376
+ * `{ enabled: false }`. With it off, `decision.review(...)` becomes a reject that keeps the
1377
+ * review reason, and the attempt records `requestedReview: true`; Console shows "Would have
1378
+ * gone to review; human review is off".
1379
+ */
1380
+ review?: ((ctx: {
1381
+ settings: z.core.$InferObjectOutput<T, {}>;
1382
+ }) => {
1383
+ enabled: boolean;
1384
+ }) | undefined;
1385
+ rewards: ({
1386
+ kind: "tier";
1387
+ reward: {
1388
+ id: string;
1389
+ title: string;
1390
+ tiers: {
1391
+ id: string;
1392
+ title: string;
1393
+ }[];
1394
+ inventory: {
1395
+ kind: "untracked";
1396
+ };
1397
+ fulfillment: {
1398
+ kind: "staff-handover";
1399
+ } | {
1400
+ kind: "automatic";
1401
+ };
1402
+ };
1403
+ tier: string;
1404
+ } | {
1405
+ kind: "integration";
1406
+ provider: "discord";
1407
+ action: "grant-role";
1408
+ roleId: string;
1409
+ } | {
1410
+ kind: "points";
1411
+ balance: string;
1412
+ amount: number;
1413
+ })[] | ((ctx: {
1414
+ settings: z.core.$InferObjectOutput<T, {}>;
1415
+ }) => Reward[]);
1416
+ evaluate?: Evaluator<z.core.$InferObjectOutput<T, {}>, QuestInput<G>, NoInfer<G>, NoInfer<D>> | undefined;
1417
+ /**
1418
+ * A content quest's performance stage: once content evaluation accepts an item, each later
1419
+ * complete and fresh sample of `metrics` (a subset of the tracker's declared metrics) gates the
1420
+ * rewards it selected.
1421
+ */
1422
+ performance?: (IsContent<G> extends true ? {
1423
+ metrics: M & readonly TriggerMetrics<G>[];
1424
+ maxAgeMs?: number;
1425
+ evaluate: (ctx: PerformanceContext<z.core.$InferObjectOutput<T, {}>, G, M[number]>) => PerformanceOutcome | Promise<PerformanceOutcome>;
1426
+ } : never) | undefined;
1427
+ }) => {
1428
+ protocol: number;
1429
+ key: string;
1430
+ describe: (input: unknown) => {
1431
+ quest: string;
1432
+ evaluatorProtocol: 2;
1433
+ title: string;
1434
+ presentation: {
1435
+ quiz?: {
1436
+ id: string;
1437
+ prompt: string;
1438
+ choices: {
1439
+ id: string;
1440
+ label: string;
1441
+ }[];
1442
+ }[] | undefined;
1443
+ instructions?: string | undefined;
1444
+ video?: {
1445
+ url: string;
1446
+ poster?: string | undefined;
1447
+ captions?: {
1448
+ url: string;
1449
+ language: string;
1450
+ label: string;
524
1451
  } | undefined;
525
1452
  } | undefined;
1453
+ };
1454
+ integrations: ("discord" | "x")[];
1455
+ fields: Record<string, {
1456
+ kind: "point-ledger";
1457
+ default: string;
1458
+ label: string;
1459
+ description?: string | undefined;
1460
+ } | {
1461
+ kind: "datetime";
1462
+ default: string;
1463
+ label: string;
1464
+ description?: string | undefined;
1465
+ } | {
1466
+ kind: "resource";
1467
+ default: string;
1468
+ source: {
1469
+ provider: "discord";
1470
+ resource: "channel";
1471
+ types: ("text" | "announcement")[];
1472
+ } | {
1473
+ provider: "discord";
1474
+ resource: "role";
1475
+ assignable: boolean;
1476
+ } | {
1477
+ provider: "domino";
1478
+ resource: "point-ledger";
1479
+ };
1480
+ label: string;
1481
+ description?: string | undefined;
1482
+ } | {
1483
+ kind: "quiz";
1484
+ default: {
1485
+ id: string;
1486
+ prompt: string;
1487
+ choices: {
1488
+ id: string;
1489
+ label: string;
1490
+ }[];
1491
+ correct: string;
1492
+ }[];
1493
+ label: string;
1494
+ description?: string | undefined;
1495
+ } | {
1496
+ kind: "text";
1497
+ default: string;
1498
+ minLength: number;
1499
+ maxLength: number;
1500
+ multiline: boolean;
1501
+ label: string;
1502
+ description?: string | undefined;
1503
+ } | {
1504
+ kind: "integer";
1505
+ default: number;
1506
+ min: number;
1507
+ max: number;
1508
+ label: string;
1509
+ description?: string | undefined;
1510
+ } | {
1511
+ kind: "boolean";
1512
+ default: boolean;
1513
+ label: string;
1514
+ description?: string | undefined;
1515
+ } | {
1516
+ kind: "choice";
1517
+ default: string;
1518
+ options: string[];
1519
+ label: string;
1520
+ description?: string | undefined;
1521
+ }>;
1522
+ values: Record<string, string | number | boolean | {
1523
+ id: string;
1524
+ prompt: string;
1525
+ choices: {
1526
+ id: string;
1527
+ label: string;
1528
+ }[];
1529
+ correct: string;
1530
+ }[]>;
1531
+ rewards: ({
1532
+ kind: "tier";
1533
+ reward: {
1534
+ id: string;
1535
+ title: string;
1536
+ tiers: {
1537
+ id: string;
1538
+ title: string;
1539
+ }[];
1540
+ inventory: {
1541
+ kind: "untracked";
1542
+ };
1543
+ fulfillment: {
1544
+ kind: "staff-handover";
1545
+ } | {
1546
+ kind: "automatic";
1547
+ };
1548
+ };
1549
+ tier: string;
526
1550
  } | {
1551
+ kind: "integration";
1552
+ provider: "discord";
1553
+ action: "grant-role";
1554
+ roleId: string;
1555
+ } | {
1556
+ kind: "points";
1557
+ balance: string;
1558
+ amount: number;
1559
+ })[];
1560
+ humanReview: boolean;
1561
+ trigger: {
527
1562
  kind: "manual";
528
1563
  input: "text";
529
1564
  constraints: {
@@ -542,47 +1577,170 @@ declare function defineQuest<T extends Record<string, z.ZodType>, const G extend
542
1577
  actor?: "staff" | "member" | undefined;
543
1578
  } | {
544
1579
  kind: "manual";
545
- input: "photo" | "quiz" | "none";
1580
+ input: "none" | "quiz" | "photo";
546
1581
  actor?: "staff" | "member" | undefined;
1582
+ } | {
1583
+ kind: "automatic";
1584
+ tracker?: {
1585
+ tracker: string;
1586
+ source: string;
1587
+ on: "new-record" | "new-observation" | "data-changed";
1588
+ beneficiary: string;
1589
+ where?: {
1590
+ path: string;
1591
+ gt?: number | {
1592
+ setting: string;
1593
+ } | undefined;
1594
+ gte?: number | {
1595
+ setting: string;
1596
+ } | undefined;
1597
+ lt?: number | {
1598
+ setting: string;
1599
+ } | undefined;
1600
+ lte?: number | {
1601
+ setting: string;
1602
+ } | undefined;
1603
+ } | {
1604
+ path: string;
1605
+ equals: string | number | boolean;
1606
+ } | ({
1607
+ path: string;
1608
+ gt?: number | {
1609
+ setting: string;
1610
+ } | undefined;
1611
+ gte?: number | {
1612
+ setting: string;
1613
+ } | undefined;
1614
+ lt?: number | {
1615
+ setting: string;
1616
+ } | undefined;
1617
+ lte?: number | {
1618
+ setting: string;
1619
+ } | undefined;
1620
+ } | {
1621
+ path: string;
1622
+ equals: string | number | boolean;
1623
+ })[] | undefined;
1624
+ enrollment?: "none" | "required" | undefined;
1625
+ since?: "activation" | "window" | "enrollment" | undefined;
1626
+ historical?: "staff" | "claim" | "automatic" | undefined;
1627
+ content?: true | undefined;
1628
+ } | undefined;
547
1629
  };
548
- requires: {
1630
+ requires: ({
1631
+ kind: "completion";
549
1632
  quest: string;
550
- }[];
1633
+ scope: "ever";
1634
+ } | {
1635
+ kind: "completion";
1636
+ quest: string;
1637
+ scope: "period";
1638
+ period: "day" | "week" | "month";
1639
+ } | {
1640
+ kind: "balance";
1641
+ balance: string;
1642
+ minimum: number;
1643
+ } | {
1644
+ kind: "group";
1645
+ group: string;
1646
+ title: string;
1647
+ })[];
551
1648
  completion: {
1649
+ kind: "progress";
1650
+ goal: {
1651
+ kind: "count";
1652
+ count: number;
1653
+ };
1654
+ window: {
1655
+ kind: "lifetime";
1656
+ } | {
1657
+ kind: "calendar";
1658
+ period: "day" | "week" | "month";
1659
+ latenessMs: number;
1660
+ } | {
1661
+ kind: "rolling";
1662
+ durationMs: number;
1663
+ };
1664
+ repeat: "repeat" | "once";
1665
+ } | {
552
1666
  kind: "streak";
553
1667
  days: number;
554
- timeZone: string;
555
1668
  } | {
556
1669
  kind: "once";
557
1670
  } | {
558
1671
  kind: "keyed";
559
1672
  };
560
1673
  visibility: "visible" | "hidden";
1674
+ profile: {
1675
+ visible: boolean;
1676
+ };
561
1677
  budgets: {
562
1678
  id: string;
563
1679
  scope: "member" | "project";
564
- period: "lifetime" | "day" | "week";
1680
+ period: "lifetime" | "day" | "week" | "month";
565
1681
  limit: number;
566
1682
  cost: number | {
567
1683
  balance: string;
568
1684
  };
569
1685
  }[];
570
1686
  performance?: {
571
- metrics: ("likes" | "replies" | "reposts" | "quotes" | "views" | "bookmarks")[];
1687
+ metrics: string[];
572
1688
  maxAgeMs: number;
573
1689
  } | undefined;
574
- profile?: {
575
- visible: boolean;
1690
+ campaign?: {
1691
+ key: string;
1692
+ title: string;
1693
+ enrollment: "none" | "required";
1694
+ window?: {
1695
+ from: number;
1696
+ until: number;
1697
+ } | undefined;
1698
+ } | undefined;
1699
+ availability?: {
1700
+ from: number;
1701
+ until: number;
576
1702
  } | undefined;
577
1703
  };
578
- evaluate(ctx: EvaluationContext<unknown, QuestInput<G>> & {
1704
+ evaluate(ctx: {
1705
+ settings: unknown;
1706
+ member: EvaluationMember;
1707
+ input: QuestInput<G>;
1708
+ /**
1709
+ * The tracker observation that admitted this attempt, and the member and verified account it
1710
+ * was attributed to. Present for a tracker trigger, with `record.data` of the tracker's type.
1711
+ * On a content source, `content` holds the body revision being evaluated, with the source's
1712
+ * body type.
1713
+ */
1714
+ tracker: TrackerTriggerContext | null;
1715
+ /**
1716
+ * When the activity happened, in epoch milliseconds: the tracker record's occurrence time, else
1717
+ * when the attempt was admitted. Budgets and daily keys use it.
1718
+ */
1719
+ eligibleAt: number;
1720
+ /** The project calendar pinned when this evaluation run started. */
1721
+ calendar: EvaluationCalendar;
1722
+ /**
1723
+ * The current evaluation run's start time in epoch milliseconds.
1724
+ * Retries and replays of that run receive the same value; a scheduled defer starts a fresh run, and the sandbox freezes
1725
+ * `Date.now()` and `new Date()` at it. Use `eligibleAt` for when the activity
1726
+ * happened.
1727
+ */
1728
+ now: number;
1729
+ trackers: TrackerReader;
1730
+ images: ImageReader;
1731
+ review: {
1732
+ text(options: TextReviewInput): Promise<TextResult>;
1733
+ photo(options: {
1734
+ image: string;
1735
+ criteria: string;
1736
+ }): Promise<PhotoResult>;
1737
+ };
1738
+ wallet: WalletReader;
1739
+ } & IntegrationReaders<readonly IntegrationModule[]> & {
579
1740
  rewards: Reward[];
580
1741
  humanReview: boolean;
581
1742
  performance?: unknown;
582
1743
  }): Promise<Decision>;
583
- };
584
- /** Publish this artifact as a reusable type. Its key names the type;
585
- * Console instances receive independent quest identities and pinned versions. */
586
- declare const defineQuestType: typeof defineQuest;
1744
+ } & ResourceHandle<"quest">;
587
1745
 
588
- export { type EvaluationContext, type PerformanceOutcome, TrackerTriggerContext, type TrackerTriggerInput, WalletBalance, WalletBalanceQuery, automatic, budget, completed, decision, defineQuest, defineQuestType, defineTieredReward, discordRole, evaluators, evidence, keyed, manual, once, points, staffHandover, untracked };
1746
+ export { ContentBody, type ContentData, ContentMetricName, type ContentTrigger, type ContentTriggerInput, DiscordMessageData, DiscordMessageTextData, DiscordReactionData, DiscordReader, type EvaluationCalendar, type EvaluationCalendarDay, type EvaluationContext, type EvaluationMember, GroupHandle, IdentityKind, ImageReader, IntegrationModule, type KeyedContext, LedgerHandle, LedgerReference, MemberIdentity, type Outcome, type PerformanceContext, type PerformanceOutcome, QuestHandle, RoleOf, Setting, Tracker, TrackerData, TrackerReader, type TrackerTrigger, TrackerTriggerContext, type TrackerTriggerInput, type TriggerAdmission, WalletReader, Where, type XContentBody, XReader, automatic, automaticFulfillment, budget, calendar, content, count, customSource, decision, defineEngagementReward, defineLeaderboard, defineLedger, defineQuest, defineQuestType, defineReferral, defineTieredReward, defineTracker, discord, earned, evaluators, evidence, keyed, manual, once, pointLedgers, points, progress, questCompleted, rolling, settings, staffHandover, streak, untracked, x };