@domino-sdk/relay 1.0.0-next.9 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +1 -1
  2. package/dist/activity-B8k9Sa_a.d.ts +9112 -0
  3. package/dist/authoring.d.ts +1053 -259
  4. package/dist/authoring.js +478 -277
  5. package/dist/automatic-outcomes-B1xrETxm.d.ts +758 -0
  6. package/dist/avatar.d.ts +2 -2
  7. package/dist/browser-J7tUpXxy.d.ts +4154 -0
  8. package/dist/browser.d.ts +11 -2613
  9. package/dist/browser.js +8 -6
  10. package/dist/{integrations-Ba5TtqTv.d.ts → capability-error-DNMwKmlL.d.ts} +124 -76
  11. package/dist/{chunk-PHU5VDLR.js → chunk-36HTX2BM.js} +389 -169
  12. package/dist/chunk-6QJ3LADK.js +112 -0
  13. package/dist/{chunk-4LBUTHD6.js → chunk-BGGKNIRP.js} +1 -1
  14. package/dist/chunk-EYH5RDIE.js +496 -0
  15. package/dist/chunk-GQKYAQM6.js +84 -0
  16. package/dist/chunk-GUP7YRR4.js +42 -0
  17. package/dist/{chunk-X2F2RAR3.js → chunk-GZ6FJAXN.js} +380 -128
  18. package/dist/chunk-JON5SESL.js +2986 -0
  19. package/dist/chunk-MC6V6VMG.js +49 -0
  20. package/dist/chunk-NPGENI7K.js +37 -0
  21. package/dist/chunk-VFHHLN6A.js +284 -0
  22. package/dist/chunk-WJSSJ7AF.js +151 -0
  23. package/dist/{chunk-7Q4BGGT6.js → chunk-XFMSUPNS.js} +1 -1
  24. package/dist/{chunk-P6FK43GG.js → chunk-ZVIRG24J.js} +145 -42
  25. package/dist/{client-CT4-S5vc.d.ts → client-XiuFnug_.d.ts} +2161 -615
  26. package/dist/{submission-input-0OOGaq8c.d.ts → groups-Ck-OxzjD.d.ts} +916 -1139
  27. package/dist/identity-integration-GxAHdKR2.d.ts +58 -0
  28. package/dist/images-Dv-P5VBw.d.ts +234 -0
  29. package/dist/index.d.ts +13 -9
  30. package/dist/index.js +17 -6
  31. package/dist/internal.d.ts +82 -44
  32. package/dist/internal.js +43 -89
  33. package/dist/offers-Cy-e4o5x.d.ts +431 -0
  34. package/dist/{pages-D3titw5B.d.ts → outcomes-kVB-Juzs.d.ts} +2157 -1448
  35. package/dist/pages-BBYD21IE.d.ts +359 -0
  36. package/dist/participant-rewards-3duLb8YJ.d.ts +668 -0
  37. package/dist/portal-proxy.js +22 -4
  38. package/dist/{profiles-DDMFBRKe.d.ts → profiles-D2aFcOxu.d.ts} +15 -15
  39. package/dist/react/index.d.ts +3038 -1029
  40. package/dist/react/index.js +1627 -779
  41. package/dist/request-error-DWduJCGV.d.ts +62 -0
  42. package/dist/schema-DfJzH2ci.d.ts +5644 -0
  43. package/dist/schema.d.ts +15 -4168
  44. package/dist/schema.js +310 -81
  45. package/dist/server/index.d.ts +81722 -0
  46. package/dist/server/index.js +2569 -0
  47. package/dist/{streaks-CwGReWGt.d.ts → streaks-CWyq8Px5.d.ts} +2 -4
  48. package/dist/submission-input-BZkm6ohU.d.ts +290 -0
  49. package/dist/vite.d.ts +1 -1
  50. package/dist/vite.js +1 -0
  51. package/dist/{wallet-BGOfFkG9.d.ts → wallet-YssWxGg8.d.ts} +35 -38
  52. package/package.json +8 -2
  53. package/dist/chunk-QR7ZA2BJ.js +0 -257
  54. package/dist/chunk-YYD4QUBO.js +0 -2348
  55. package/dist/chunk-ZWY3R6B3.js +0 -26
  56. package/dist/collection-BGneJ6Bk.d.ts +0 -114
  57. package/dist/images-BTgk6OmC.d.ts +0 -1564
  58. package/dist/point-ledgers-iS00Z_v0.d.ts +0 -37
  59. package/dist/schema-Di3aLSiK.d.ts +0 -3532
@@ -1,56 +1,34 @@
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';
1
3
  import { z } from 'zod';
2
4
  export { z } from 'zod';
3
- import { C as ContentPolicy, g as ContentMetric, E as EngagementDefinition, l as leaderboardAuthoringSchema, r as referralAuthoringSchema, h as AdmittedContent, D as DiscordMember, T as TextEvidence, U as UrlEvidence, e as TextOptions, f as UrlOptions } from './submission-input-0OOGaq8c.js';
4
- import { Q as QuizContent, a as StreakPolicy } from './streaks-CwGReWGt.js';
5
- import { R as ResourceSource, S as Setting, O as Observation, X as XReader, D as DiscordMessage, o as observationTriggerSchema, B as Budget, I as IntegerSettings, a as IntegrationProvider } from './integrations-Ba5TtqTv.js';
6
- import { T as TrackerDefinition, I as IdentityKind, c as customSourceSchema, W as WithRecordData, a as TrackerSource, t as trackerDefinitionSchema, b as Tracker, d as TrackerData, x as xSearchSourceSchema, X as XTweet, e as TrackerTriggerContext, f as TrackerTriggerPolicy, g as TrackerReader, h as ImageReader, i as Where, j as TrackerTriggerMode, k as WhereSetting } from './images-BTgk6OmC.js';
7
- export { l as TrackerDataSchema, m as TrackerPage, n as trackerDataSchema, o as trackerTriggerContextSchema } from './images-BTgk6OmC.js';
8
- import { d as TextReviewInput, e as TextResult, P as PhotoResult, r as rewardSchema, t as triggerSchema, Q as QuestPresentation, a as QuestProfile, b as QuizEvidence, D as Decision, f as TieredRewardDefinition } from './schema-Di3aLSiK.js';
9
- import { h as WalletConnection, S as SolanaBalance, L as LinkedWallet, i as WalletBalanceQuery, j as WalletBalance } from './wallet-BGOfFkG9.js';
10
- export { E as EvmChainId, k as isEvmChainId } from './wallet-BGOfFkG9.js';
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';
11
16
  export { f as formatUnits, p as parseUnits } from './units-CwgsPB_r.js';
12
17
 
13
- /** Legacy `id` names an authoring key, never a server resource ID. */
14
- type AuthoringIdentity = {
18
+ declare function defineLedger(input: z.input<typeof pointLedgerDeclarationSchema>): {
19
+ name: string;
20
+ description: string;
15
21
  key: string;
16
- id?: string;
17
- } | {
18
- key?: never; /** @deprecated Use key. */
19
- id: string;
20
- };
21
-
22
- /** Discover posts automatically; historical release remains an explicit policy. */
23
- declare function content(tracker: TrackerDefinition, policy?: Partial<Pick<ContentPolicy, "enrollment" | "posts" | "historical">>): {
24
- kind: "automatic";
25
- content: {
26
- tracker: string;
27
- window: {
28
- start: number;
29
- end?: number | undefined;
30
- };
31
- enrollment: "required" | "none";
32
- posts: "after-enrollment" | "since-start";
33
- historical: "staff" | "automatic" | "claim";
34
- };
35
- };
36
- declare function perContent(): {
37
- kind: "keyed";
38
- perContent: true;
39
- key: (ctx: {
40
- content?: AdmittedContent | null;
41
- }) => string;
42
- };
22
+ } & ResourceHandle<"ledger">;
43
23
  /** One independent cumulative formula; management changes capture a new scoring boundary. */
44
- declare function defineEngagementReward<const M extends readonly [ContentMetric, ...ContentMetric[]]>(input: {
24
+ declare function defineEngagementReward<const M extends readonly [string, ...string[]]>(input: {
45
25
  key: string;
46
- qualifiedBy: string | {
47
- key: string;
48
- };
49
- balance: string;
26
+ qualifiedBy: QuestHandle;
27
+ ledger: LedgerReference;
50
28
  metrics: M;
51
29
  baseline: "historical";
52
30
  maxAgeMs?: number;
53
- budget?: EngagementDefinition["budget"];
31
+ budgets?: EngagementBudget[];
54
32
  target: (input: {
55
33
  metrics: Record<M[number], number>;
56
34
  }) => number;
@@ -60,14 +38,14 @@ declare function defineEngagementReward<const M extends readonly [ContentMetric,
60
38
  key: string;
61
39
  qualifiedBy: string;
62
40
  balance: string;
63
- metrics: ("likes" | "replies" | "reposts" | "quotes" | "views" | "bookmarks")[];
41
+ metrics: string[];
64
42
  baseline: "historical";
65
43
  maxAgeMs: number;
66
- budget: {
67
- projectDaily?: number | undefined;
68
- memberDaily?: number | undefined;
69
- projectLifetime?: number | undefined;
70
- };
44
+ budgets: {
45
+ scope: "member" | "project";
46
+ period: "lifetime" | "day" | "week" | "month";
47
+ limit: number;
48
+ }[];
71
49
  };
72
50
  score(raw: unknown): {
73
51
  target: number;
@@ -75,15 +53,68 @@ declare function defineEngagementReward<const M extends readonly [ContentMetric,
75
53
  };
76
54
  };
77
55
  /**
78
- * One milestone per quest, after `days` consecutive community days with an accepted attempt.
79
- * Multiple accepted attempts occupy one day. The day comes from the attempt's trusted occurrence
80
- * time: a tracker record's (or observation's) `occurredAt` for `automatic({ tracker })`, and the
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
81
59
  * submission's admission time for `manual()`, so a manual streak counts the days a member
82
- * submitted. Not available on content quests or prerequisite-only `automatic()`.
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()`.
83
62
  */
84
- declare const streak: (options: Omit<StreakPolicy, "kind">) => StreakPolicy;
85
- declare function defineReferral(input: Omit<z.input<typeof referralAuthoringSchema>, "key" | "id"> & AuthoringIdentity): {
86
- id: string;
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
+ }): {
87
118
  title: string;
88
119
  rewards: {
89
120
  inviter: ({
@@ -100,6 +131,8 @@ declare function defineReferral(input: Omit<z.input<typeof referralAuthoringSche
100
131
  };
101
132
  fulfillment: {
102
133
  kind: "staff-handover";
134
+ } | {
135
+ kind: "automatic";
103
136
  };
104
137
  };
105
138
  tier: string;
@@ -122,6 +155,8 @@ declare function defineReferral(input: Omit<z.input<typeof referralAuthoringSche
122
155
  };
123
156
  fulfillment: {
124
157
  kind: "staff-handover";
158
+ } | {
159
+ kind: "automatic";
125
160
  };
126
161
  };
127
162
  tier: string;
@@ -140,7 +175,6 @@ declare function defineReferral(input: Omit<z.input<typeof referralAuthoringSche
140
175
  kind: "external";
141
176
  };
142
177
  enabled: boolean;
143
- inviterGroup?: string | undefined;
144
178
  milestones: {
145
179
  id: string;
146
180
  count: number;
@@ -158,6 +192,8 @@ declare function defineReferral(input: Omit<z.input<typeof referralAuthoringSche
158
192
  };
159
193
  fulfillment: {
160
194
  kind: "staff-handover";
195
+ } | {
196
+ kind: "automatic";
161
197
  };
162
198
  };
163
199
  tier: string;
@@ -177,12 +213,41 @@ declare function defineReferral(input: Omit<z.input<typeof referralAuthoringSche
177
213
  maxPoints?: number | undefined;
178
214
  }[];
179
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";
180
240
  };
181
- declare function defineLeaderboard(input: Omit<z.input<typeof leaderboardAuthoringSchema>, "key" | "id"> & AuthoringIdentity): {
182
- id: string;
183
- balance: string;
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
+ }): {
184
248
  title: string;
185
- group?: string | undefined;
249
+ balance: string;
250
+ access: "participants" | "public";
186
251
  score: {
187
252
  kind: "balance";
188
253
  } | {
@@ -198,7 +263,6 @@ declare function defineLeaderboard(input: Omit<z.input<typeof leaderboardAuthori
198
263
  } | {
199
264
  kind: "calendar";
200
265
  period: "day" | "week" | "month";
201
- timeZone: string;
202
266
  };
203
267
  kind: "earned";
204
268
  quests?: string[] | undefined;
@@ -216,17 +280,54 @@ declare function defineLeaderboard(input: Omit<z.input<typeof leaderboardAuthori
216
280
  } | {
217
281
  kind: "calendar";
218
282
  period: "day" | "week" | "month";
219
- timeZone: string;
220
283
  };
221
284
  };
222
- access: "participants" | "public";
223
285
  key: string;
224
- };
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>;
225
321
  declare const x: {
226
- /** Posts matching an X search. Each record's `data` is the provider's post payload. */
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
+ */
227
328
  search: (input: {
228
329
  query: string;
229
- }) => z.output<typeof xSearchSourceSchema> & WithRecordData<XTweet>;
330
+ }) => z.output<typeof xSearchSourceSchema> & WithRecordData<XTweet> & WithContent<XContentBody, XContentMetric>;
230
331
  };
231
332
  /**
232
333
  * Records your own code sends with `trackers.ingest`. `data` is a zod object schema that every
@@ -237,18 +338,75 @@ declare const x: {
237
338
  * trigger from the tracker. A record states each account's `kind` unless the source names exactly
238
339
  * one.
239
340
  */
240
- declare function customSource<S extends z.ZodObject>(namespace: string, options: {
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: {
241
363
  identities?: IdentityKind[];
242
- accounts?: string[];
364
+ accounts?: A;
243
365
  data: S;
244
- }): z.output<typeof customSourceSchema> & WithRecordData<z.input<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;
245
369
  declare function defineTracker<S extends TrackerSource>(input: Omit<z.input<typeof trackerDefinitionSchema>, "source"> & {
246
370
  source: S;
247
- }): Tracker<TrackerData<S>>;
371
+ }): Tracker<TrackerData<S>> & ContentOf<S> & WithAccountRoles<SourceRoles<S>>;
248
372
  type ChannelTypes = Extract<ResourceSource, {
249
373
  resource: "channel";
250
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>;
251
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;
252
410
  roles(options?: {
253
411
  assignable?: boolean;
254
412
  }): ResourceSource;
@@ -263,8 +421,8 @@ type Label = {
263
421
  };
264
422
  declare const settings: {
265
423
  pointLedger(options: Label & {
266
- default: string;
267
- }): Setting<"point-ledger", z.ZodDefault<z.ZodString>>;
424
+ default?: LedgerHandle;
425
+ }): Setting<"point-ledger", z.ZodPrefault<z.core.$ZodBranded<z.ZodUnion<[z.ZodString, z.ZodLiteral<"">]>, "ledger-reference", "out">>>;
268
426
  datetime(options: Label & {
269
427
  default: string;
270
428
  }): Setting<"datetime", z.ZodDefault<z.ZodPipe<z.ZodISODateTime, z.ZodTransform<string, string>>>>;
@@ -306,17 +464,11 @@ declare const settings: {
306
464
  };
307
465
 
308
466
  type Reward = z.infer<typeof rewardSchema>;
309
- declare const points: (balance: string, amount: number) => {
467
+ declare const points: (ledger: LedgerReference, amount: number) => {
310
468
  kind: "points";
311
469
  balance: string;
312
470
  amount: number;
313
471
  };
314
- declare const discordRole: (roleId: string) => {
315
- kind: "integration";
316
- provider: "discord";
317
- action: "grant-role";
318
- roleId: string;
319
- };
320
472
 
321
473
  declare const evidence: {
322
474
  text: (options?: TextOptions) => {
@@ -360,14 +512,38 @@ declare function manual(options: {
360
512
  input: "none";
361
513
  actor: "staff";
362
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
+ };
363
538
  /** A tracker trigger: which observations of which tracker run the quest, and for whom. */
364
- type TrackerTriggerInput<T extends Tracker = Tracker, W extends Where<TrackerData<T>> | undefined = Where<TrackerData<T>> | undefined> = {
539
+ type TrackerTriggerInput<T extends Tracker = Tracker, W extends Where<TrackerData<T>> | undefined = Where<TrackerData<T>> | undefined> = TriggerAdmission & {
365
540
  /** The tracker handle `defineTracker` returns. */
366
541
  tracker: T;
367
542
  /**
368
543
  * Which observations fire. `"new-record"`: each record's first observation (the default for X
369
- * trackers, where it means each newly collected post). `"new-observation"`: each observation
370
- * 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
371
547
  * new record, or a current observation whose `data` differs from the previous one.
372
548
  */
373
549
  on?: TrackerTriggerMode;
@@ -380,53 +556,107 @@ type TrackerTriggerInput<T extends Tracker = Tracker, W extends Where<TrackerDat
380
556
  where?: W;
381
557
  /**
382
558
  * The record account whose member the quest pays: `"author"` (the default), `"inReplyTo"` on
383
- * an X tracker, or a named account a custom source declares in `accounts`. Skipped when that
384
- * 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.
385
570
  */
386
- beneficiary?: string;
571
+ historical?: "staff" | "claim" | "automatic";
387
572
  };
388
573
  /** Type-only markers a tracker trigger carries into `defineQuest`. They never exist at runtime. */
389
574
  declare const triggerData: unique symbol;
390
575
  declare const triggerSettings: unique symbol;
576
+ declare const triggerBody: unique symbol;
577
+ declare const triggerMetrics: unique symbol;
391
578
  /**
392
579
  * A tracker trigger whose records carry `data` of type `D` and whose filter compares with the
393
- * settings `S`. `defineQuest` types `ctx.tracker` from `D` and checks `S` against its integer
394
- * settings.
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.
395
582
  */
396
- type TrackerTrigger<D = unknown, S extends string = never> = {
583
+ type TrackerTrigger<D = unknown, S extends string = never, B = never, M extends string = never> = {
397
584
  kind: "automatic";
398
585
  tracker: TrackerTriggerPolicy;
399
586
  readonly [triggerData]?: D;
400
587
  readonly [triggerSettings]?: S;
588
+ readonly [triggerBody]?: B;
589
+ readonly [triggerMetrics]?: M;
590
+ };
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
+ };
401
599
  };
402
- type TriggerData<G> = G extends TrackerTrigger<infer D, string> ? unknown extends D ? unknown : D : unknown;
600
+ type TriggerData<G> = G extends {
601
+ readonly [triggerData]?: infer D;
602
+ } ? unknown extends D ? unknown : Exclude<D, undefined> : unknown;
403
603
  type TriggerSettings<G> = G extends {
404
604
  readonly [triggerSettings]?: infer S;
405
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;
406
621
  /**
407
- * An automatic quest. With no argument it runs once its prerequisites are complete; with an
408
- * observation it runs for each matching observation; with a tracker it runs for each observation
409
- * its firing mode and filter admit, for the member Relay attributes the beneficiary account to.
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.
410
625
  */
411
626
  declare function automatic(): {
412
627
  kind: "automatic";
413
628
  };
414
- declare function automatic(observation: z.infer<typeof observationTriggerSchema>): {
415
- kind: "automatic";
416
- observation: z.infer<typeof observationTriggerSchema>;
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";
417
642
  };
418
- declare function automatic<T extends Tracker, const W extends Where<TrackerData<T>> | undefined = undefined>(input: TrackerTriggerInput<T, W>): TrackerTrigger<TrackerData<T>, WhereSetting<W>>;
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>>;
419
650
  /**
420
651
  * What a trigger `G` supplies under key `K`: `Present` when the trigger has it, null when it cannot,
421
652
  * and `Present | null` when `G` is not known.
422
653
  */
423
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;
424
- /** `ctx.tracker` for a trigger: non-null and typed for a tracker trigger, null for others. */
425
- type ContextTracker<G> = Supplied<G, "tracker", TrackerTriggerContext<TriggerData<G>>, TrackerTriggerContext>;
426
- /** `ctx.content` for a trigger: the admitted post for a content trigger, null for others. */
427
- type ContextContent<G> = Supplied<G, "content", AdmittedContent, AdmittedContent>;
428
- /** `ctx.observation` for a trigger: the observation for an observation trigger, null for others. */
429
- type ContextObservation<G> = Supplied<G, "observation", Observation, Observation>;
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>;
430
660
  /**
431
661
  * What a `keyed()` completion key reads. TypeScript cannot carry the trigger into a completion
432
662
  * built inline, so `tracker` stays nullable here; the evaluator's `ctx.tracker` is typed.
@@ -435,18 +665,23 @@ type KeyedContext = {
435
665
  member: {
436
666
  id: string;
437
667
  };
438
- content?: AdmittedContent | null;
439
- observation: Observation | null;
440
668
  /** The pinned tracker observation of a tracker-triggered quest; null for other triggers. */
441
669
  tracker: TrackerTriggerContext | null;
442
670
  eligibleAt: number;
671
+ /** The evaluation run's pinned project calendar. */
672
+ calendar: EvaluationCalendar;
443
673
  /** The attempt's evaluation time; see {@link EvaluationContext.now}. */
444
674
  now: number;
445
675
  };
446
- declare const budget: (definition: Budget) => {
676
+ declare const budget: (definition: Omit<Budget, "id" | "cost"> & {
677
+ key: string;
678
+ cost: number | {
679
+ ledger: LedgerReference;
680
+ };
681
+ }) => {
447
682
  id: string;
448
683
  scope: "member" | "project";
449
- period: "lifetime" | "day" | "week";
684
+ period: "lifetime" | "day" | "week" | "month";
450
685
  limit: number;
451
686
  cost: number | {
452
687
  balance: string;
@@ -456,8 +691,30 @@ declare const keyed: (key: (ctx: KeyedContext) => string) => {
456
691
  kind: "keyed";
457
692
  key: (ctx: KeyedContext) => string;
458
693
  };
459
- declare const completed: (quest: AuthoringIdentity | string) => {
460
- 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";
461
718
  };
462
719
  declare const untracked: () => {
463
720
  kind: "untracked";
@@ -465,11 +722,17 @@ declare const untracked: () => {
465
722
  declare const staffHandover: () => {
466
723
  kind: "staff-handover";
467
724
  };
468
- declare function defineTieredReward(input: Omit<TieredRewardDefinition, "id"> & AuthoringIdentity): {
725
+ declare const automaticFulfillment: () => {
726
+ kind: "automatic";
727
+ };
728
+ declare function defineTieredReward<const T extends readonly {
469
729
  key: string;
470
- /** @deprecated Authoring key alias. Use key. */
471
- id: string;
472
- 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"]) => {
473
736
  kind: "tier";
474
737
  reward: {
475
738
  id: string;
@@ -483,25 +746,23 @@ declare function defineTieredReward(input: Omit<TieredRewardDefinition, "id"> &
483
746
  };
484
747
  fulfillment: {
485
748
  kind: "staff-handover";
749
+ } | {
750
+ kind: "automatic";
486
751
  };
487
752
  };
488
753
  tier: string;
489
754
  };
490
- };
755
+ } & ResourceHandle<"tiered-reward">;
491
756
  declare const once: () => {
492
757
  kind: "once";
493
758
  };
494
- type Outcome = {
759
+ type Outcome = (Omit<Extract<Decision, {
495
760
  kind: "accept";
761
+ }>, "rewards"> & {
496
762
  rewards?: Reward[];
497
- } | {
498
- kind: "review";
499
- reason: string;
500
- rewards?: Reward[];
501
- } | {
502
- kind: "reject";
503
- reason: string;
504
- };
763
+ }) | Exclude<Decision, {
764
+ kind: "accept";
765
+ }>;
505
766
  /**
506
767
  * A performance evaluator's answer. It gates the rewards content evaluation already selected, so
507
768
  * it carries none: a `rewards` value fails the evaluation.
@@ -520,9 +781,11 @@ type PerformanceOutcome = {
520
781
  declare function accept(): {
521
782
  kind: "accept";
522
783
  };
523
- declare function accept(options: {
524
- rewards?: Reward[];
525
- }): Outcome;
784
+ declare function accept(options: Omit<Extract<Outcome, {
785
+ kind: "accept";
786
+ }>, "kind">): Extract<Outcome, {
787
+ kind: "accept";
788
+ }>;
526
789
  declare function review(options: {
527
790
  reason: string;
528
791
  rewards?: undefined;
@@ -530,12 +793,23 @@ declare function review(options: {
530
793
  kind: "review";
531
794
  reason: string;
532
795
  };
533
- declare function review(options: {
534
- reason: string;
535
- rewards?: Reward[];
536
- }): Outcome;
796
+ declare function review(options: Omit<Extract<Outcome, {
797
+ kind: "review";
798
+ }>, "kind">): Extract<Outcome, {
799
+ kind: "review";
800
+ }>;
537
801
  declare const decision: {
538
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
+ }>;
539
813
  reject: (options: {
540
814
  reason: string;
541
815
  }) => {
@@ -544,42 +818,70 @@ declare const decision: {
544
818
  };
545
819
  review: typeof review;
546
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
+ };
547
848
  /**
548
- * What an evaluator reads. `G` is the quest's trigger: `tracker`, `content` and `observation` are
549
- * non-null for the trigger that supplies them and null otherwise. `G` defaults to `any`, which
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
550
851
  * leaves them nullable and lets a shared evaluator, such as `evaluators.photo()`, fit every quest.
551
852
  */
853
+ type IntegrationReaders<D extends readonly IntegrationModule[]> = Pick<{
854
+ x: XReader;
855
+ discord: DiscordReader;
856
+ }, D[number]["provider"]>;
552
857
  type EvaluationContext<T, I = {
553
858
  photo: string;
554
- }, G = any> = {
859
+ }, G = any, D extends readonly IntegrationModule[] = readonly IntegrationModule[]> = {
555
860
  settings: T;
556
- member: {
557
- id: string;
558
- };
861
+ member: EvaluationMember;
559
862
  input: I;
560
- /** The admitted post of a content quest. */
561
- content: ContextContent<G>;
562
- /** The observation of an observation-triggered quest. */
563
- observation: ContextObservation<G>;
564
863
  /**
565
864
  * The tracker observation that admitted this attempt, and the member and verified account it
566
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.
567
868
  */
568
869
  tracker: ContextTracker<G>;
569
870
  /**
570
- * When the activity happened, in epoch milliseconds: the observation's or tracker record's
571
- * 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.
572
873
  */
573
874
  eligibleAt: number;
875
+ /** The project calendar pinned when this evaluation run started. */
876
+ calendar: EvaluationCalendar;
574
877
  /**
575
- * The attempt's evaluation time, in epoch milliseconds: when its first evaluation started.
576
- * 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
577
880
  * `Date.now()` and `new Date()` at it. Use `eligibleAt` for when the activity
578
881
  * happened.
579
882
  */
580
883
  now: number;
581
884
  trackers: TrackerReader;
582
- x: XReader;
583
885
  images: ImageReader;
584
886
  review: {
585
887
  text(options: TextReviewInput): Promise<TextResult>;
@@ -588,31 +890,11 @@ type EvaluationContext<T, I = {
588
890
  criteria: string;
589
891
  }): Promise<PhotoResult>;
590
892
  };
591
- discord: {
592
- member(): Promise<DiscordMember | null>;
593
- message(input: {
594
- channelId: string;
595
- messageId: string;
596
- }): Promise<DiscordMessage | null>;
597
- };
598
- wallet: {
599
- /** The member's newest linked Solana wallet. */
600
- connection(): Promise<WalletConnection | null>;
601
- /** SOL held by the newest linked Solana wallet. */
602
- solanaBalance(): Promise<SolanaBalance | null>;
603
- /** Every wallet the member has linked to this project, pinned once per attempt. */
604
- list(): Promise<LinkedWallet[]>;
605
- /**
606
- * The native or token balance of the member's pinned linked wallets on one chain: all wallets of
607
- * that family, or `address` (which must be one of them). No wallets gives `total: "0"` and
608
- * `wallets: []`. Provider failures throw; they never read as a zero balance.
609
- */
610
- balance(query: WalletBalanceQuery): Promise<WalletBalance>;
611
- };
612
- };
893
+ wallet: WalletReader;
894
+ } & IntegrationReaders<D>;
613
895
  type Evaluator<T, I = {
614
896
  photo: string;
615
- }, G = any> = (ctx: EvaluationContext<T, I, G>) => Promise<Outcome>;
897
+ }, G = any, D extends readonly IntegrationModule[] = readonly []> = (ctx: EvaluationContext<T, I, G, D>) => Promise<Outcome>;
616
898
  declare const evaluators: {
617
899
  quiz(answerKey: QuizEvidence["answers"], options?: {
618
900
  minimumCorrect?: number;
@@ -645,21 +927,50 @@ type IntegerSettingBounds<G, T> = [
645
927
  ] extends [never] ? unknown : {
646
928
  readonly "The tracker filter compares with settings that are not integer settings of this quest": Exclude<TriggerSettings<G>, IntegerSettings<T>>;
647
929
  };
648
- declare function defineQuest<T extends Record<string, Setting>, const G extends Trigger, const M extends readonly [ContentMetric, ...ContentMetric[]] = readonly [
649
- ContentMetric,
650
- ...ContentMetric[]
651
- ]>(definition: AuthoringIdentity & {
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) & {
652
962
  title: string | ((ctx: {
653
- settings: z.output<z.ZodObject<T>>;
963
+ settings: z.core.$InferObjectOutput<T, {}>;
654
964
  }) => string);
655
- settings: z.ZodObject<T>;
656
- presentation?: (ctx: {
657
- settings: z.output<z.ZodObject<T>>;
658
- }) => QuestPresentation;
965
+ settings: z.ZodObject<T, z.core.$strip>;
966
+ presentation?: ((ctx: {
967
+ settings: z.core.$InferObjectOutput<T, {}>;
968
+ }) => QuestPresentation) | undefined;
659
969
  trigger: G & NoInfer<IntegerSettingBounds<G, T>>;
660
- integrations?: IntegrationProvider[];
661
- requires?: ReturnType<typeof completed>[];
662
- completion: ReturnType<typeof once> | ReturnType<typeof keyed> | StreakPolicy;
970
+ integrations?: D | undefined;
971
+ requires?: readonly Prerequisite[];
972
+ campaign?: CampaignDefinition;
973
+ availability?: AvailabilityWindow;
663
974
  visibility?: "visible" | "hidden";
664
975
  /**
665
976
  * `{ visible: true }` lists the quest's completions on participant profiles
@@ -673,37 +984,59 @@ declare function defineQuest<T extends Record<string, Setting>, const G extends
673
984
  * review reason, and the attempt records `requestedReview: true`; Console shows "Would have
674
985
  * gone to review; human review is off".
675
986
  */
676
- review?: (ctx: {
677
- settings: z.output<z.ZodObject<T>>;
987
+ review?: ((ctx: {
988
+ settings: z.core.$InferObjectOutput<T, {}>;
678
989
  }) => {
679
990
  enabled: boolean;
680
- };
681
- rewards: Reward[] | ((ctx: {
682
- settings: z.output<z.ZodObject<T>>;
683
- }) => Reward[]);
684
- evaluate?: Evaluator<z.output<z.ZodObject<T>>, QuestInput<G>, NoInfer<G>>;
685
- performance?: G extends {
686
- content: unknown;
687
- } ? {
688
- metrics: M;
689
- maxAgeMs?: number;
690
- evaluate: (ctx: {
691
- settings: z.output<z.ZodObject<T>>;
692
- member: {
991
+ }) | undefined;
992
+ rewards: ({
993
+ kind: "tier";
994
+ reward: {
995
+ id: string;
996
+ title: string;
997
+ tiers: {
693
998
  id: string;
999
+ title: string;
1000
+ }[];
1001
+ inventory: {
1002
+ kind: "untracked";
694
1003
  };
695
- content: AdmittedContent;
696
- metrics: Record<M[number], number>;
697
- observedAt: number;
698
- }) => PerformanceOutcome | Promise<PerformanceOutcome>;
699
- } : never;
700
- }): {
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;
701
1036
  key: string;
702
- /** @deprecated Authoring key alias. Use key. */
703
- id: string;
704
1037
  describe: (input: unknown) => {
705
1038
  quest: string;
706
- runtimeVersion: 1 | 2;
1039
+ evaluatorProtocol: 2;
707
1040
  title: string;
708
1041
  presentation: {
709
1042
  quiz?: {
@@ -725,7 +1058,7 @@ declare function defineQuest<T extends Record<string, Setting>, const G extends
725
1058
  } | undefined;
726
1059
  } | undefined;
727
1060
  };
728
- integrations: "discord"[];
1061
+ integrations: ("discord" | "x")[];
729
1062
  fields: Record<string, {
730
1063
  kind: "point-ledger";
731
1064
  default: string;
@@ -740,9 +1073,6 @@ declare function defineQuest<T extends Record<string, Setting>, const G extends
740
1073
  kind: "resource";
741
1074
  default: string;
742
1075
  source: {
743
- provider: "domino";
744
- resource: "point-ledger";
745
- } | {
746
1076
  provider: "discord";
747
1077
  resource: "channel";
748
1078
  types: ("text" | "announcement")[];
@@ -750,6 +1080,9 @@ declare function defineQuest<T extends Record<string, Setting>, const G extends
750
1080
  provider: "discord";
751
1081
  resource: "role";
752
1082
  assignable: boolean;
1083
+ } | {
1084
+ provider: "domino";
1085
+ resource: "point-ledger";
753
1086
  };
754
1087
  label: string;
755
1088
  description?: string | undefined;
@@ -816,41 +1149,50 @@ declare function defineQuest<T extends Record<string, Setting>, const G extends
816
1149
  };
817
1150
  fulfillment: {
818
1151
  kind: "staff-handover";
1152
+ } | {
1153
+ kind: "automatic";
819
1154
  };
820
1155
  };
821
1156
  tier: string;
822
- } | {
823
- kind: "points";
824
- balance: string;
825
- amount: number;
826
1157
  } | {
827
1158
  kind: "integration";
828
1159
  provider: "discord";
829
1160
  action: "grant-role";
830
1161
  roleId: string;
1162
+ } | {
1163
+ kind: "points";
1164
+ balance: string;
1165
+ amount: number;
831
1166
  })[];
832
1167
  humanReview: boolean;
833
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
+ } | {
834
1190
  kind: "automatic";
835
- observation?: {
836
- source: string;
837
- type: string;
838
- } | undefined;
839
- content?: {
840
- tracker: string;
841
- window: {
842
- start: number;
843
- end?: number | undefined;
844
- };
845
- enrollment: "required" | "none";
846
- posts: "after-enrollment" | "since-start";
847
- historical: "staff" | "automatic" | "claim";
848
- } | undefined;
849
1191
  tracker?: {
850
1192
  tracker: string;
851
- source: "custom" | "x-search";
1193
+ source: string;
1194
+ on: "new-record" | "new-observation" | "data-changed";
852
1195
  beneficiary: string;
853
- on?: "new-record" | "new-observation" | "data-changed" | undefined;
854
1196
  where?: {
855
1197
  path: string;
856
1198
  gt?: number | {
@@ -886,67 +1228,519 @@ declare function defineQuest<T extends Record<string, Setting>, const G extends
886
1228
  path: string;
887
1229
  equals: string | number | boolean;
888
1230
  })[] | undefined;
1231
+ enrollment?: "none" | "required" | undefined;
1232
+ since?: "activation" | "window" | "enrollment" | undefined;
1233
+ historical?: "staff" | "claim" | "automatic" | undefined;
1234
+ content?: true | undefined;
889
1235
  } | undefined;
1236
+ };
1237
+ requires: ({
1238
+ kind: "completion";
1239
+ quest: string;
1240
+ scope: "ever";
890
1241
  } | {
891
- kind: "manual";
892
- input: "text";
893
- constraints: {
894
- required: boolean;
895
- minLength: number;
896
- maxLength: number;
897
- };
898
- actor?: "staff" | "member" | undefined;
1242
+ kind: "completion";
1243
+ quest: string;
1244
+ scope: "period";
1245
+ period: "day" | "week" | "month";
899
1246
  } | {
900
- kind: "manual";
901
- input: "url";
902
- constraints: {
903
- required: boolean;
904
- allowedHosts?: string[] | undefined;
905
- };
906
- actor?: "staff" | "member" | undefined;
1247
+ kind: "balance";
1248
+ balance: string;
1249
+ minimum: number;
907
1250
  } | {
908
- kind: "manual";
909
- input: "photo" | "quiz" | "none";
910
- actor?: "staff" | "member" | undefined;
911
- };
912
- requires: {
913
- quest: string;
914
- }[];
1251
+ kind: "group";
1252
+ group: string;
1253
+ title: string;
1254
+ })[];
915
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
+ } | {
916
1273
  kind: "streak";
917
1274
  days: number;
918
- timeZone: string;
919
1275
  } | {
920
1276
  kind: "once";
921
1277
  } | {
922
1278
  kind: "keyed";
923
1279
  };
924
1280
  visibility: "visible" | "hidden";
1281
+ profile: {
1282
+ visible: boolean;
1283
+ };
925
1284
  budgets: {
926
1285
  id: string;
927
1286
  scope: "member" | "project";
928
- period: "lifetime" | "day" | "week";
1287
+ period: "lifetime" | "day" | "week" | "month";
929
1288
  limit: number;
930
1289
  cost: number | {
931
1290
  balance: string;
932
1291
  };
933
1292
  }[];
934
1293
  performance?: {
935
- metrics: ("likes" | "replies" | "reposts" | "quotes" | "views" | "bookmarks")[];
1294
+ metrics: string[];
936
1295
  maxAgeMs: number;
937
1296
  } | undefined;
938
- profile?: {
939
- visible: boolean;
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;
940
1309
  } | undefined;
941
1310
  };
942
- evaluate(ctx: EvaluationContext<unknown, QuestInput<G>> & {
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[]> & {
943
1347
  rewards: Reward[];
944
1348
  humanReview: boolean;
945
1349
  performance?: unknown;
946
1350
  }): Promise<Decision>;
947
- };
1351
+ } & ResourceHandle<"quest">;
948
1352
  /** Publish this artifact as a reusable type. Its key names the type;
949
1353
  * Console instances receive independent quest identities and pinned versions. */
950
- declare const defineQuestType: typeof defineQuest;
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;
1451
+ } | undefined;
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;
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: {
1562
+ kind: "manual";
1563
+ input: "text";
1564
+ constraints: {
1565
+ required: boolean;
1566
+ minLength: number;
1567
+ maxLength: number;
1568
+ };
1569
+ actor?: "staff" | "member" | undefined;
1570
+ } | {
1571
+ kind: "manual";
1572
+ input: "url";
1573
+ constraints: {
1574
+ required: boolean;
1575
+ allowedHosts?: string[] | undefined;
1576
+ };
1577
+ actor?: "staff" | "member" | undefined;
1578
+ } | {
1579
+ kind: "manual";
1580
+ input: "none" | "quiz" | "photo";
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;
1629
+ };
1630
+ requires: ({
1631
+ kind: "completion";
1632
+ quest: string;
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
+ })[];
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
+ } | {
1666
+ kind: "streak";
1667
+ days: number;
1668
+ } | {
1669
+ kind: "once";
1670
+ } | {
1671
+ kind: "keyed";
1672
+ };
1673
+ visibility: "visible" | "hidden";
1674
+ profile: {
1675
+ visible: boolean;
1676
+ };
1677
+ budgets: {
1678
+ id: string;
1679
+ scope: "member" | "project";
1680
+ period: "lifetime" | "day" | "week" | "month";
1681
+ limit: number;
1682
+ cost: number | {
1683
+ balance: string;
1684
+ };
1685
+ }[];
1686
+ performance?: {
1687
+ metrics: string[];
1688
+ maxAgeMs: number;
1689
+ } | undefined;
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;
1702
+ } | undefined;
1703
+ };
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[]> & {
1740
+ rewards: Reward[];
1741
+ humanReview: boolean;
1742
+ performance?: unknown;
1743
+ }): Promise<Decision>;
1744
+ } & ResourceHandle<"quest">;
951
1745
 
952
- export { type EvaluationContext, ImageReader, type KeyedContext, type PerformanceOutcome, Setting, Tracker, TrackerData, TrackerReader, type TrackerTrigger, TrackerTriggerContext, type TrackerTriggerInput, WalletBalance, WalletBalanceQuery, Where, XReader, automatic, budget, completed, content, customSource, decision, defineEngagementReward, defineLeaderboard, defineQuest, defineQuestType, defineReferral, defineTieredReward, defineTracker, discord, discordRole, evaluators, evidence, keyed, manual, once, perContent, pointLedgers, points, settings, staffHandover, streak, untracked, x };
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 };