@domino-sdk/relay 1.54.0 → 1.56.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 (65) hide show
  1. package/CHANGELOG.md +1859 -0
  2. package/dist/analytics-URV-mxjH.d.ts +482 -0
  3. package/dist/{attempt-captures-QC4kTA44.d.ts → attempt-captures-CxxO7DeD.d.ts} +1 -1
  4. package/dist/authoring.d.ts +277 -40
  5. package/dist/authoring.js +142 -14
  6. package/dist/{automatic-outcomes-CVyZHxir.d.ts → automatic-outcomes-DxW_v5Wc.d.ts} +5 -2
  7. package/dist/avatar.d.ts +1 -1
  8. package/dist/browser.d.ts +7 -7
  9. package/dist/browser.js +10 -10
  10. package/dist/{capability-error-FQGGb5xS.d.ts → capability-error-DSd8EMQC.d.ts} +76 -2
  11. package/dist/{chunk-RP4LLEON.js → chunk-ABJ4G47X.js} +1 -1
  12. package/dist/{chunk-IELNFM3V.js → chunk-BHHUSBSD.js} +97 -8
  13. package/dist/chunk-BJYMTCWG.js +950 -0
  14. package/dist/{chunk-K6TVMNU4.js → chunk-CK7HO32Z.js} +1 -1
  15. package/dist/{chunk-GTQJSDBS.js → chunk-CXKXPB7K.js} +32 -16
  16. package/dist/{chunk-TL5TL5RD.js → chunk-G6XVBYH7.js} +4 -4
  17. package/dist/{chunk-S2PMKZSX.js → chunk-H2MD6E7Z.js} +21 -2
  18. package/dist/{chunk-YVC3B72P.js → chunk-INSWI2VZ.js} +1 -1
  19. package/dist/{chunk-XFAYQFRO.js → chunk-KBVH4XZC.js} +1 -1
  20. package/dist/{chunk-MLIXJPKL.js → chunk-MHPKEVEW.js} +1 -0
  21. package/dist/{chunk-7BNCLWAO.js → chunk-MNU6UPXY.js} +1 -1
  22. package/dist/{chunk-JL7J3EQQ.js → chunk-NK6EER33.js} +46 -16
  23. package/dist/{chunk-QIDQWXSF.js → chunk-OTITLABX.js} +2 -2
  24. package/dist/{chunk-53JMTUWG.js → chunk-QNQNKIAA.js} +1 -1
  25. package/dist/{chunk-ZJ3FVZRP.js → chunk-RBPMT53S.js} +132 -99
  26. package/dist/chunk-ULQU7KC4.js +704 -0
  27. package/dist/chunk-VSHV7FEA.js +344 -0
  28. package/dist/{chunk-LPHXTZDA.js → chunk-W5U2WXG3.js} +2 -2
  29. package/dist/{client-CzNtl8UO.d.ts → client-bX3oTpRu.d.ts} +111 -8
  30. package/dist/{deployments-ovtqtAcx.d.ts → deployments-D3lxfQMB.d.ts} +1436 -185
  31. package/dist/{groups-B5R1RCsl.d.ts → groups-DPE004_V.d.ts} +135 -139
  32. package/dist/index.d.ts +8 -8
  33. package/dist/index.js +9 -9
  34. package/dist/integrations-CcD5NPEA.d.ts +633 -0
  35. package/dist/internal.d.ts +11 -10
  36. package/dist/internal.js +9 -9
  37. package/dist/{offers-CH1RZekg.d.ts → offers-CtzMeB7O.d.ts} +207 -2
  38. package/dist/{pages-BTlOg8sl.d.ts → pages-BlLqB8ZQ.d.ts} +82 -2
  39. package/dist/portal-proxy.d.ts +11 -1
  40. package/dist/portal-proxy.js +27 -6
  41. package/dist/{profiles-Cdv4BSd_.d.ts → profiles-BoOK03cR.d.ts} +2 -0
  42. package/dist/react/index.d.ts +566 -13
  43. package/dist/react/index.js +105 -15
  44. package/dist/runtime/authoring.js +1 -1
  45. package/dist/runtime/chunks/NDB42VFF.js +1 -0
  46. package/dist/runtime/manifest.json +3 -3
  47. package/dist/runtime/schema.js +1 -1
  48. package/dist/{schema-BJ9bOgpN.d.ts → schema-C4m9RhCR.d.ts} +166 -6
  49. package/dist/schema.d.ts +383 -79
  50. package/dist/schema.js +105 -41
  51. package/dist/server/index.d.ts +11 -10
  52. package/dist/server/index.js +1590 -1175
  53. package/dist/{submission-input-BNah53go.d.ts → submission-input-wTiYGdgA.d.ts} +2 -2
  54. package/dist/{telegram-browser-C36j_6v-.d.ts → telegram-browser-Bh3i0HiH.d.ts} +1 -1
  55. package/dist/testing.d.ts +85 -12
  56. package/dist/testing.js +322 -37
  57. package/dist/{transport-C8BlCzmF.d.ts → transport-CnKA-_RL.d.ts} +7625 -1265
  58. package/dist/vite.d.ts +54 -1
  59. package/dist/vite.js +35 -0
  60. package/dist/{x-BfQcsDp0.d.ts → x-1czZFVUW.d.ts} +1 -1
  61. package/package.json +3 -2
  62. package/dist/chunk-2NUD237O.js +0 -102
  63. package/dist/chunk-CCE2JWES.js +0 -1083
  64. package/dist/integrations-CllF-kWg.d.ts +0 -314
  65. package/dist/runtime/chunks/AVRVSLHX.js +0 -1
package/dist/testing.js CHANGED
@@ -1,23 +1,25 @@
1
1
  import {
2
2
  attemptCaptureSchema
3
- } from "./chunk-7BNCLWAO.js";
3
+ } from "./chunk-MNU6UPXY.js";
4
4
  import {
5
5
  CapabilityError
6
6
  } from "./chunk-4OC7REYX.js";
7
7
  import {
8
8
  parseImageResult
9
- } from "./chunk-LPHXTZDA.js";
9
+ } from "./chunk-W5U2WXG3.js";
10
10
  import {
11
11
  imageRequestSchema,
12
12
  xConnectionSchema,
13
13
  xPostSchema,
14
14
  xProfileSchema,
15
15
  xRequestSchema
16
- } from "./chunk-K6TVMNU4.js";
16
+ } from "./chunk-CK7HO32Z.js";
17
17
  import {
18
+ pointBalanceSchema,
19
+ profileReferralSchema,
18
20
  telegramChatMemberSchema,
19
21
  telegramMemberInputSchema
20
- } from "./chunk-2NUD237O.js";
22
+ } from "./chunk-VSHV7FEA.js";
21
23
  import {
22
24
  contentPerformanceSnapshotSchema,
23
25
  cosmosNetworkSchema,
@@ -28,6 +30,8 @@ import {
28
30
  evmChainIdSchema,
29
31
  identifier,
30
32
  linkedWalletSchema,
33
+ maxMemberCompletions,
34
+ memberCompletionSchema,
31
35
  memberIdentitySchema,
32
36
  photoResultSchema,
33
37
  quizEvidenceSchema,
@@ -46,7 +50,7 @@ import {
46
50
  urlEvidenceSchema,
47
51
  validateSubmissionValue,
48
52
  walletBalanceSchema
49
- } from "./chunk-IELNFM3V.js";
53
+ } from "./chunk-BHHUSBSD.js";
50
54
 
51
55
  // src/testing/run.ts
52
56
  import * as z3 from "zod";
@@ -189,6 +193,30 @@ var telegramRequestSchema = z.strictObject({
189
193
  kind: z.literal("telegram"),
190
194
  input: telegramMemberInputSchema
191
195
  });
196
+ var memberStateRequestSchemas = {
197
+ "member-balance": z.strictObject({
198
+ kind: z.literal("member-balance"),
199
+ ledger: identifier
200
+ }),
201
+ "member-completions": z.strictObject({
202
+ kind: z.literal("member-completions"),
203
+ quest: identifier.nullable(),
204
+ since: z.number().int().nonnegative().safe().nullable(),
205
+ limit: z.number().int().min(1).max(maxMemberCompletions)
206
+ }),
207
+ "member-groups": z.strictObject({ kind: z.literal("member-groups") }),
208
+ "member-enrolled": z.strictObject({
209
+ kind: z.literal("member-enrolled"),
210
+ campaign: identifier
211
+ }),
212
+ "member-referrals": z.strictObject({
213
+ kind: z.literal("member-referrals"),
214
+ program: identifier
215
+ })
216
+ };
217
+ function unlistedRequest(request) {
218
+ return request.kind === "telegram" || request.kind === "member-balance" || request.kind === "member-completions" || request.kind === "member-groups" || request.kind === "member-enrolled" || request.kind === "member-referrals";
219
+ }
192
220
  var capabilityRequestSchema = z.discriminatedUnion("kind", [
193
221
  capabilityRequestSchemas["wallet-balance"],
194
222
  capabilityRequestSchemas["tracker-content"],
@@ -201,7 +229,12 @@ var capabilityRequestSchema = z.discriminatedUnion("kind", [
201
229
  capabilityRequestSchemas.discord,
202
230
  capabilityRequestSchemas["wallet-list"],
203
231
  capabilityRequestSchemas["member-identities"],
204
- telegramRequestSchema
232
+ telegramRequestSchema,
233
+ memberStateRequestSchemas["member-balance"],
234
+ memberStateRequestSchemas["member-completions"],
235
+ memberStateRequestSchemas["member-groups"],
236
+ memberStateRequestSchemas["member-enrolled"],
237
+ memberStateRequestSchemas["member-referrals"]
205
238
  ]);
206
239
  function parseCapabilityRequest(raw) {
207
240
  return capabilityRequestSchema.safeParse(raw);
@@ -245,6 +278,16 @@ function parseCapabilityResult(request, value) {
245
278
  return z.array(memberIdentitySchema).min(1).nullable().parse(value);
246
279
  case "telegram":
247
280
  return telegramChatMemberSchema.nullable().parse(value);
281
+ case "member-balance":
282
+ return pointBalanceSchema.parse(value);
283
+ case "member-completions":
284
+ return z.array(memberCompletionSchema).max(request.limit).parse(value);
285
+ case "member-groups":
286
+ return z.array(identifier).parse(value);
287
+ case "member-enrolled":
288
+ return z.boolean().parse(value);
289
+ case "member-referrals":
290
+ return profileReferralSchema.parse(value);
248
291
  }
249
292
  }
250
293
  function imageReferences(input) {
@@ -274,10 +317,23 @@ function capabilityEvidence(request) {
274
317
  );
275
318
  }
276
319
  var readerFactories = {
277
- member: (call, input) => ({
278
- ...input.member,
279
- identities: () => call({ kind: "member-identities" })
280
- }),
320
+ member: (call, input) => {
321
+ const key = (reference) => typeof reference === "string" ? reference : reference.key;
322
+ return {
323
+ ...input.member,
324
+ identities: () => call({ kind: "member-identities" }),
325
+ balance: (ledger) => call({ kind: "member-balance", ledger: key(ledger) }),
326
+ completions: ({ quest, since, limit = 100 } = {}) => call({
327
+ kind: "member-completions",
328
+ quest: quest === void 0 ? null : key(quest),
329
+ since: since ?? null,
330
+ limit: limit > 100 ? 100 : limit
331
+ }),
332
+ groups: () => call({ kind: "member-groups" }),
333
+ enrolled: (campaign) => call({ kind: "member-enrolled", campaign: key(campaign) }),
334
+ referrals: (program) => call({ kind: "member-referrals", program: key(program) })
335
+ };
336
+ },
281
337
  discord: (call) => ({
282
338
  member: () => call({ kind: "discord", input: {} }),
283
339
  message: (input) => call({ kind: "discord", input })
@@ -476,21 +532,21 @@ function install(now, seed, restores) {
476
532
  const crypto = globalThis.crypto;
477
533
  if (crypto) {
478
534
  restores.push(
479
- replace(crypto, "getRandomValues", (array2) => {
480
- if (!integerArrays.some((type) => array2 instanceof type)) {
535
+ replace(crypto, "getRandomValues", (array3) => {
536
+ if (!integerArrays.some((type) => array3 instanceof type)) {
481
537
  throw new DOMException(
482
538
  "getRandomValues takes an integer typed array",
483
539
  "TypeMismatchError"
484
540
  );
485
541
  }
486
- if (array2.byteLength > 65536) {
542
+ if (array3.byteLength > 65536) {
487
543
  throw new DOMException(
488
544
  "getRandomValues takes at most 65536 bytes",
489
545
  "QuotaExceededError"
490
546
  );
491
547
  }
492
- fill(new Uint8Array(array2.buffer, array2.byteOffset, array2.byteLength));
493
- return array2;
548
+ fill(new Uint8Array(array3.buffer, array3.byteOffset, array3.byteLength));
549
+ return array3;
494
550
  })
495
551
  );
496
552
  restores.push(
@@ -510,6 +566,10 @@ function install(now, seed, restores) {
510
566
 
511
567
  // src/testing/facts.ts
512
568
  import * as z2 from "zod";
569
+ var campaignFactSchema = z2.strictObject({
570
+ key: identifier,
571
+ enrolled: z2.boolean()
572
+ });
513
573
  var TestSetupError = class extends Error {
514
574
  constructor(message) {
515
575
  super(message);
@@ -524,6 +584,38 @@ function fakeFor(facts, request) {
524
584
  answer: facts.member?.identities,
525
585
  args: []
526
586
  };
587
+ case "member-balance":
588
+ return {
589
+ name: "member.balances",
590
+ reader: "member.balance",
591
+ answer: facts.member?.balances,
592
+ args: []
593
+ };
594
+ case "member-completions":
595
+ return {
596
+ name: "member.completions",
597
+ answer: facts.member?.completions,
598
+ args: []
599
+ };
600
+ case "member-groups":
601
+ return {
602
+ name: "member.groups",
603
+ answer: facts.member?.groups,
604
+ args: []
605
+ };
606
+ case "member-enrolled":
607
+ return {
608
+ name: "member.campaigns",
609
+ reader: "member.enrolled",
610
+ answer: facts.member?.campaigns,
611
+ args: []
612
+ };
613
+ case "member-referrals":
614
+ return {
615
+ name: "member.referrals",
616
+ answer: facts.member?.referrals,
617
+ args: []
618
+ };
527
619
  case "wallet-list":
528
620
  return {
529
621
  name: "wallet.list",
@@ -627,7 +719,7 @@ function factsAnswerer(facts) {
627
719
  async function ask(fake) {
628
720
  if (fake.answer === void 0) {
629
721
  throw new TestSetupError(
630
- `The quest called ctx.${fake.name}, but the test gave no answer: set facts.${fake.name}`
722
+ `The quest called ctx.${fake.reader ?? fake.name}, but the test gave no answer: set facts.${fake.name}`
631
723
  );
632
724
  }
633
725
  try {
@@ -663,6 +755,79 @@ function factsAnswerer(facts) {
663
755
  }
664
756
  return outcome;
665
757
  }
758
+ function state(fake, schema) {
759
+ let outcome = pins.get(fake.name);
760
+ if (!outcome) {
761
+ outcome = ask(fake).then((answered) => {
762
+ if ("error" in answered) {
763
+ return answered;
764
+ }
765
+ const parsed = z2.array(schema).safeParse(answered.value);
766
+ if (!parsed.success) {
767
+ throw new TestSetupError(
768
+ `facts.${fake.name} is not a list Relay reads: ${z2.prettifyError(parsed.error)}`
769
+ );
770
+ }
771
+ return { value: parsed.data };
772
+ });
773
+ pins.set(fake.name, outcome);
774
+ }
775
+ return outcome;
776
+ }
777
+ async function memberState(request, fake) {
778
+ if (request.kind === "member-balance") {
779
+ const pinned2 = await state(fake, pointBalanceSchema);
780
+ if ("error" in pinned2) {
781
+ return pinned2;
782
+ }
783
+ const balance = pinned2.value.find(
784
+ ({ ledger }) => ledger.key === request.ledger || ledger.id === request.ledger
785
+ );
786
+ return balance ? { value: balance } : failure("author-error", `Point ledger not found: ${request.ledger}`);
787
+ }
788
+ if (request.kind === "member-groups") {
789
+ const pinned2 = await state(fake, identifier);
790
+ return "error" in pinned2 ? pinned2 : {
791
+ value: [...new Set(pinned2.value)].sort(
792
+ (a, b) => a < b ? -1 : a > b ? 1 : 0
793
+ )
794
+ };
795
+ }
796
+ if (request.kind === "member-enrolled") {
797
+ const pinned2 = await state(fake, campaignFactSchema);
798
+ if ("error" in pinned2) {
799
+ return pinned2;
800
+ }
801
+ const campaign = pinned2.value.find(
802
+ ({ key }) => key === request.campaign
803
+ );
804
+ return campaign ? { value: campaign.enrolled } : failure("author-error", `Campaign not found: ${request.campaign}`);
805
+ }
806
+ if (request.kind === "member-referrals") {
807
+ const pinned2 = await state(fake, profileReferralSchema);
808
+ if ("error" in pinned2) {
809
+ return pinned2;
810
+ }
811
+ const progress = pinned2.value.find(
812
+ ({ key, program }) => key === request.program || program === request.program
813
+ );
814
+ return progress ? { value: progress } : failure(
815
+ "author-error",
816
+ `Referral program not found: ${request.program}`
817
+ );
818
+ }
819
+ const pinned = await state(fake, memberCompletionSchema);
820
+ if ("error" in pinned) {
821
+ return pinned;
822
+ }
823
+ const { quest, since, limit } = request;
824
+ const order = (completion) => completion.completedAt ?? -1;
825
+ return {
826
+ value: pinned.value.filter(
827
+ (completion) => (quest === null || completion.quest === quest) && (since === null || completion.completedAt !== null && completion.completedAt >= since)
828
+ ).sort((a, b) => order(b) - order(a)).slice(0, limit)
829
+ };
830
+ }
666
831
  function own(fake, account, link) {
667
832
  if (account !== null) {
668
833
  return ask(fake);
@@ -680,6 +845,12 @@ function factsAnswerer(facts) {
680
845
  case "member-identities":
681
846
  case "wallet-list":
682
847
  return pin(request);
848
+ case "member-balance":
849
+ case "member-completions":
850
+ case "member-groups":
851
+ case "member-enrolled":
852
+ case "member-referrals":
853
+ return memberState(request, fake);
683
854
  case "x": {
684
855
  const { operation } = request.input;
685
856
  if (operation === "connection") {
@@ -901,7 +1072,13 @@ function hostContext(run, answer) {
901
1072
  const evidence = typeof input.evidence === "string" ? input.evidence : void 0;
902
1073
  const calendar = evaluationCalendar({ segments: run.segments }, eligibleAt);
903
1074
  const calls = [];
1075
+ const diagnostics = [];
904
1076
  const problems = [];
1077
+ const delivered = /* @__PURE__ */ new WeakSet();
1078
+ const delivering = (error) => {
1079
+ delivered.add(error);
1080
+ return error;
1081
+ };
905
1082
  let sequence = 0;
906
1083
  async function deliver(request, sequence2) {
907
1084
  for (const provider of capabilityIntegrations(request)) {
@@ -931,19 +1108,17 @@ function hostContext(run, answer) {
931
1108
  const call = async (raw) => {
932
1109
  const current = sequence++;
933
1110
  if (current >= maxCapabilityCalls) {
934
- const error = new TestSetupError(
935
- `An evaluation run makes at most ${maxCapabilityCalls} capability calls; the quest made more`
936
- );
937
- problems.push(error);
938
- throw error;
1111
+ throw capabilityLimitError();
939
1112
  }
940
1113
  const parsed = parseCapabilityRequest(raw);
941
1114
  if (!parsed.success) {
942
- throw CapabilityError.from({
943
- code: "author-error",
944
- message: z3.prettifyError(parsed.error),
945
- retryable: false
946
- });
1115
+ throw delivering(
1116
+ CapabilityError.from({
1117
+ code: "author-error",
1118
+ message: z3.prettifyError(parsed.error),
1119
+ retryable: false
1120
+ })
1121
+ );
947
1122
  }
948
1123
  let outcome;
949
1124
  try {
@@ -952,12 +1127,12 @@ function hostContext(run, answer) {
952
1127
  problems.push(error instanceof Error ? error : new Error(String(error)));
953
1128
  throw error;
954
1129
  }
955
- if (parsed.data.kind !== "telegram") {
1130
+ if (!unlistedRequest(parsed.data)) {
956
1131
  calls.push({ sequence: current, request: parsed.data, outcome });
957
1132
  calls.sort((a, b) => a.sequence - b.sequence);
958
1133
  }
959
1134
  if ("error" in outcome) {
960
- throw CapabilityError.from(outcome.error);
1135
+ throw delivering(CapabilityError.from(outcome.error));
961
1136
  }
962
1137
  return outcome.value;
963
1138
  };
@@ -984,15 +1159,98 @@ function hostContext(run, answer) {
984
1159
  calendar,
985
1160
  now,
986
1161
  ...performance ? { performance } : {},
987
- ...readers
1162
+ ...readers,
1163
+ // Relay's hosted runtime passes no `diagnose`, so it records none of this.
1164
+ diagnose: ({ code, message }) => {
1165
+ diagnostics.push({ code, message });
1166
+ }
1167
+ };
1168
+ return {
1169
+ context,
1170
+ calls,
1171
+ diagnostics,
1172
+ problems,
1173
+ delivered,
1174
+ release,
1175
+ now,
1176
+ seed: run.seed
988
1177
  };
989
- return { context, calls, problems, release, now, seed: run.seed };
1178
+ }
1179
+ var EvaluatorError = class extends Error {
1180
+ code = "evaluator-error";
1181
+ retryable = false;
1182
+ constructor(thrown) {
1183
+ super(thrownMessage(thrown), { cause: thrown });
1184
+ this.name = "EvaluatorError";
1185
+ }
1186
+ };
1187
+ function thrownMessage(error) {
1188
+ let message = "";
1189
+ try {
1190
+ if (error !== null && typeof error === "object" && typeof error.message === "string") {
1191
+ const { name, message: text } = error;
1192
+ const label = typeof name === "string" && name.trim() ? name.trim() : "Error";
1193
+ message = text.trim() ? label + ": " + text.trim() : label;
1194
+ } else {
1195
+ message = typeof error === "string" ? error : String(error);
1196
+ }
1197
+ } catch {
1198
+ }
1199
+ return message.trim().slice(0, 1e3) || "The evaluator threw without a message";
1200
+ }
1201
+ function capabilityLimitError() {
1202
+ return new CapabilityError(
1203
+ "capability-limit",
1204
+ `An evaluation run makes at most ${maxCapabilityCalls} capability calls, shared by all capabilities`,
1205
+ { retryable: false }
1206
+ );
1207
+ }
1208
+ function uncaught(error, delivered) {
1209
+ const seen = /* @__PURE__ */ new WeakSet();
1210
+ const queue = [error];
1211
+ const push = (value) => {
1212
+ if (queue.length < 200) {
1213
+ queue.push(value);
1214
+ }
1215
+ };
1216
+ for (let next = 0; next < queue.length && next < 100; next++) {
1217
+ const value = queue[next];
1218
+ if (value === null || typeof value !== "object" && typeof value !== "function" || seen.has(value)) {
1219
+ continue;
1220
+ }
1221
+ seen.add(value);
1222
+ if (delivered.has(value)) {
1223
+ return error;
1224
+ }
1225
+ const read = (key) => {
1226
+ try {
1227
+ return value[key];
1228
+ } catch {
1229
+ return void 0;
1230
+ }
1231
+ };
1232
+ for (const key of ["cause", "errors", "error", "suppressed"]) {
1233
+ const field = read(key);
1234
+ if (key === "errors") {
1235
+ if (Array.isArray(field)) {
1236
+ field.slice(0, 100).forEach(push);
1237
+ }
1238
+ } else if (field !== void 0) {
1239
+ push(field);
1240
+ }
1241
+ }
1242
+ }
1243
+ return new EvaluatorError(error);
990
1244
  }
991
1245
  function failure2(message) {
992
1246
  return { error: { code: "author-error", message, retryable: false } };
993
1247
  }
994
1248
  function createTestContext(quest, options = {}) {
995
- const { problems: _, ...context } = hostContext(
1249
+ const {
1250
+ problems: _,
1251
+ delivered: __,
1252
+ ...context
1253
+ } = hostContext(
996
1254
  hostedRun(quest, options),
997
1255
  factsAnswerer(options.facts ?? {})
998
1256
  );
@@ -1013,9 +1271,9 @@ function evaluateHosted(quest, host) {
1013
1271
  try {
1014
1272
  restore = installDeterminism(host.now, host.seed);
1015
1273
  decision = await Promise.race([
1016
- quest.evaluate(
1017
- host.context
1018
- ),
1274
+ (async () => quest.evaluate(host.context))().catch((error) => {
1275
+ throw uncaught(error, host.delivered);
1276
+ }),
1019
1277
  new Promise((_, reject) => {
1020
1278
  timer = setTimeout(
1021
1279
  () => reject(
@@ -1036,6 +1294,9 @@ function evaluateHosted(quest, host) {
1036
1294
  if (host.problems[0]) {
1037
1295
  throw host.problems[0];
1038
1296
  }
1297
+ if (decision === void 0) {
1298
+ throw new EvaluatorError(new Error("Evaluator returned no decision"));
1299
+ }
1039
1300
  if (decision.kind === "accept" || decision.kind === "review") {
1040
1301
  const issue = rewardSelectionIssue(
1041
1302
  decision.rewards ?? [],
@@ -1045,7 +1306,12 @@ function evaluateHosted(quest, host) {
1045
1306
  throw new Error(issue);
1046
1307
  }
1047
1308
  }
1048
- return { decision, calls: host.calls, release: host.release };
1309
+ return {
1310
+ decision,
1311
+ calls: host.calls,
1312
+ release: host.release,
1313
+ diagnostics: host.diagnostics
1314
+ };
1049
1315
  });
1050
1316
  }
1051
1317
  async function runQuest(quest, options = {}) {
@@ -1222,10 +1488,27 @@ function captureAnswerer(facts, fallback, diverged) {
1222
1488
  if (fact?.outcome && !reason) {
1223
1489
  return fact.outcome;
1224
1490
  }
1225
- if (request.kind === "telegram") {
1491
+ if (unlistedRequest(request)) {
1226
1492
  if (!answerFallback) {
1493
+ const [reader, fact2] = {
1494
+ telegram: ["ctx.telegram.member()", "facts.telegram"],
1495
+ "member-balance": ["ctx.member.balance()", "facts.member.balances"],
1496
+ "member-completions": [
1497
+ "ctx.member.completions()",
1498
+ "facts.member.completions"
1499
+ ],
1500
+ "member-groups": ["ctx.member.groups()", "facts.member.groups"],
1501
+ "member-enrolled": [
1502
+ "ctx.member.enrolled()",
1503
+ "facts.member.campaigns"
1504
+ ],
1505
+ "member-referrals": [
1506
+ "ctx.member.referrals()",
1507
+ "facts.member.referrals"
1508
+ ]
1509
+ }[request.kind];
1227
1510
  throw new TestSetupError(
1228
- `Capability call ${sequence}, ctx.telegram.member(), is not in the capture (${reason ?? "new"}): pass facts.telegram to answer it`
1511
+ `Capability call ${sequence}, ${reader}, is not in the capture (${reason ?? "new"}): pass ${fact2} to answer it`
1229
1512
  );
1230
1513
  }
1231
1514
  return answerFallback(request);
@@ -1297,6 +1580,7 @@ async function replayAttempt(quest, capture, options = {}) {
1297
1580
  export {
1298
1581
  CapabilityError,
1299
1582
  DecisionAssertionError,
1583
+ EvaluatorError,
1300
1584
  TestSetupError,
1301
1585
  createTestContext,
1302
1586
  defaultMember,
@@ -1307,6 +1591,7 @@ export {
1307
1591
  expectProgress,
1308
1592
  expectReject,
1309
1593
  expectReview,
1594
+ maxCapabilityCalls,
1310
1595
  replayAttempt,
1311
1596
  runQuest,
1312
1597
  trackerObservation,