@ixo/asks-mcp 1.6.0 → 1.8.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 (2) hide show
  1. package/dist/asks-mcp.mjs +391 -367
  2. package/package.json +1 -1
package/dist/asks-mcp.mjs CHANGED
@@ -8197,12 +8197,12 @@ var init_report = __esm({
8197
8197
 
8198
8198
  // ../../packages/openhands-sdk/src/rubric/survey.ts
8199
8199
  function surveyOptionsProblem(options) {
8200
- const L4 = SURVEY_LIMITS;
8200
+ const L5 = SURVEY_LIMITS;
8201
8201
  if (!Array.isArray(options)) return "A survey needs its options.";
8202
- if (options.length < L4.optionsMin || options.length > L4.optionsMax) return `A survey has ${L4.optionsMin}\u2013${L4.optionsMax} options.`;
8202
+ if (options.length < L5.optionsMin || options.length > L5.optionsMax) return `A survey has ${L5.optionsMin}\u2013${L5.optionsMax} options.`;
8203
8203
  const seen2 = /* @__PURE__ */ new Set();
8204
8204
  for (const option of options) {
8205
- if (typeof option !== "string" || !option.trim() || option.trim().length > L4.optionMax) return `Every option is 1\u2013${L4.optionMax} characters.`;
8205
+ if (typeof option !== "string" || !option.trim() || option.trim().length > L5.optionMax) return `Every option is 1\u2013${L5.optionMax} characters.`;
8206
8206
  if (/[\n\r]/.test(option)) return "An option is one line.";
8207
8207
  const key = option.trim().toLowerCase();
8208
8208
  if (seen2.has(key)) return `"${option.trim()}" is listed twice.`;
@@ -8427,31 +8427,31 @@ function chainOf(raw) {
8427
8427
  function blockOf(raw) {
8428
8428
  const block2 = raw;
8429
8429
  if (!block2 || typeof block2 !== "object") return null;
8430
- const L4 = CALL_LIMITS;
8430
+ const L5 = CALL_LIMITS;
8431
8431
  const picture2 = (one) => {
8432
8432
  const it2 = one;
8433
- return Boolean(it2) && https(it2.url) && line(it2.alt, L4.alt) && maybe(it2.caption, L4.caption);
8433
+ return Boolean(it2) && https(it2.url) && line(it2.alt, L5.alt) && maybe(it2.caption, L5.caption);
8434
8434
  };
8435
8435
  const file3 = (one) => {
8436
8436
  const it2 = one;
8437
- return Boolean(it2) && https(it2.url) && line(it2.name, L4.name) && maybe(it2.note, L4.note);
8437
+ return Boolean(it2) && https(it2.url) && line(it2.name, L5.name) && maybe(it2.note, L5.note);
8438
8438
  };
8439
8439
  const step = (one) => {
8440
8440
  const it2 = one;
8441
- return Boolean(it2) && line(it2.title, L4.stepTitle) && maybe(it2.text, L4.stepText);
8441
+ return Boolean(it2) && line(it2.title, L5.stepTitle) && maybe(it2.text, L5.stepText);
8442
8442
  };
8443
- const paragraph = (one) => line(one, L4.paragraph);
8443
+ const paragraph = (one) => line(one, L5.paragraph);
8444
8444
  const withCaption = (value, caption) => caption === void 0 ? value : { ...value, caption };
8445
8445
  const withNote = (value, note) => note === void 0 ? value : { ...value, note };
8446
8446
  switch (block2.kind) {
8447
8447
  case "story":
8448
- return someOf(block2.paragraphs, L4.paragraphs, paragraph) ? { kind: "story", paragraphs: [...block2.paragraphs] } : null;
8448
+ return someOf(block2.paragraphs, L5.paragraphs, paragraph) ? { kind: "story", paragraphs: [...block2.paragraphs] } : null;
8449
8449
  case "cover":
8450
- return https(block2.url) && line(block2.alt, L4.alt) && maybe(block2.caption, L4.caption) ? withCaption({ kind: "cover", url: block2.url, alt: block2.alt }, block2.caption) : null;
8450
+ return https(block2.url) && line(block2.alt, L5.alt) && maybe(block2.caption, L5.caption) ? withCaption({ kind: "cover", url: block2.url, alt: block2.alt }, block2.caption) : null;
8451
8451
  case "pictures":
8452
- return someOf(block2.items, L4.items, picture2) ? { kind: "pictures", items: block2.items.map((one) => withCaption({ url: one.url, alt: one.alt }, one.caption)) } : null;
8452
+ return someOf(block2.items, L5.items, picture2) ? { kind: "pictures", items: block2.items.map((one) => withCaption({ url: one.url, alt: one.alt }, one.caption)) } : null;
8453
8453
  case "diagram":
8454
- if (!line(block2.title, L4.title) || !someOf(block2.steps, L4.steps, step) || !(block2.source === void 0 || lines(block2.source, L4.source))) return null;
8454
+ if (!line(block2.title, L5.title) || !someOf(block2.steps, L5.steps, step) || !(block2.source === void 0 || lines(block2.source, L5.source))) return null;
8455
8455
  return {
8456
8456
  kind: "diagram",
8457
8457
  title: block2.title,
@@ -8459,29 +8459,29 @@ function blockOf(raw) {
8459
8459
  ...block2.source === void 0 ? {} : { source: block2.source }
8460
8460
  };
8461
8461
  case "data":
8462
- return line(block2.title, L4.title) && lines(block2.csv, L4.csv) && maybe(block2.note, L4.note) ? withNote({ kind: "data", title: block2.title, csv: block2.csv }, block2.note) : null;
8462
+ return line(block2.title, L5.title) && lines(block2.csv, L5.csv) && maybe(block2.note, L5.note) ? withNote({ kind: "data", title: block2.title, csv: block2.csv }, block2.note) : null;
8463
8463
  case "files":
8464
- return someOf(block2.items, L4.items, file3) ? { kind: "files", items: block2.items.map((one) => withNote({ url: one.url, name: one.name }, one.note)) } : null;
8464
+ return someOf(block2.items, L5.items, file3) ? { kind: "files", items: block2.items.map((one) => withNote({ url: one.url, name: one.name }, one.note)) } : null;
8465
8465
  case "start":
8466
- return lines(block2.prompt, L4.start) ? { kind: "start", prompt: block2.prompt } : null;
8466
+ return lines(block2.prompt, L5.start) ? { kind: "start", prompt: block2.prompt } : null;
8467
8467
  }
8468
8468
  return null;
8469
8469
  }
8470
8470
  function callOf(raw) {
8471
8471
  const call2 = raw;
8472
8472
  if (!call2 || typeof call2 !== "object") return null;
8473
- const L4 = CALL_LIMITS;
8473
+ const L5 = CALL_LIMITS;
8474
8474
  if (typeof call2.slug !== "string" || !CALL_SLUG.test(call2.slug)) return null;
8475
8475
  if (!CALL_LEGS.includes(call2.leg)) return null;
8476
- if (!line(call2.title, L4.title) || !line(call2.lede, L4.lede) || !line(call2.poster, L4.poster)) return null;
8477
- if (!Array.isArray(call2.points) || call2.points.length === 0 || call2.points.length > L4.lines || !call2.points.every((one) => finite(one) && one >= 0 && one <= 100)) return null;
8476
+ if (!line(call2.title, L5.title) || !line(call2.lede, L5.lede) || !line(call2.poster, L5.poster)) return null;
8477
+ if (!Array.isArray(call2.points) || call2.points.length === 0 || call2.points.length > L5.lines || !call2.points.every((one) => finite(one) && one >= 0 && one <= 100)) return null;
8478
8478
  const money2 = call2.money;
8479
8479
  if (!money2 || typeof money2 !== "object") return null;
8480
8480
  if (!amount(money2.prize) || !whole(money2.runnersN, 0, 5) || !amount(money2.runnersEach) || !amount(money2.entryEach) || !whole(money2.entryUpTo, 1, 1e4)) return null;
8481
8481
  const share = call2.share;
8482
8482
  if (share !== void 0 && (!share || typeof share !== "object" || !nonNegative(share.network) || !nonNegative(share.node) || share.network + share.node >= 100)) return null;
8483
8483
  const sponsor = call2.sponsor;
8484
- if (sponsor !== void 0 && (!sponsor || typeof sponsor !== "object" || typeof sponsor.slug !== "string" || !CALL_SLUG.test(sponsor.slug) || !line(sponsor.name, L4.sponsorName) || typeof sponsor.node !== "string" || !ENTITY_DID.test(sponsor.node))) return null;
8484
+ if (sponsor !== void 0 && (!sponsor || typeof sponsor !== "object" || typeof sponsor.slug !== "string" || !CALL_SLUG.test(sponsor.slug) || !line(sponsor.name, L5.sponsorName) || typeof sponsor.node !== "string" || !ENTITY_DID.test(sponsor.node))) return null;
8485
8485
  if (!date5(call2.closes) || !date5(call2.drop) || !date5(call2.pick)) return null;
8486
8486
  let legs;
8487
8487
  if (call2.legs !== void 0) {
@@ -8495,7 +8495,7 @@ function callOf(raw) {
8495
8495
  legs[name8] = id;
8496
8496
  }
8497
8497
  }
8498
- if (!Array.isArray(call2.blocks) || call2.blocks.length > L4.blocks) return null;
8498
+ if (!Array.isArray(call2.blocks) || call2.blocks.length > L5.blocks) return null;
8499
8499
  const blocks = call2.blocks.map(blockOf);
8500
8500
  if (blocks.some((block2) => block2 === null)) return null;
8501
8501
  let review = null;
@@ -8503,11 +8503,11 @@ function callOf(raw) {
8503
8503
  if (call2.kind !== "review" || call2.mode !== "hire") return null;
8504
8504
  const subject = call2.subject;
8505
8505
  if (subject !== void 0) {
8506
- if (!subject || typeof subject !== "object" || !line(subject.name, L4.subjectName)) return null;
8507
- if (subject.version !== void 0 && !line(subject.version, L4.version)) return null;
8508
- if (subject.where !== void 0 && !line(subject.where, L4.where)) return null;
8506
+ if (!subject || typeof subject !== "object" || !line(subject.name, L5.subjectName)) return null;
8507
+ if (subject.version !== void 0 && !line(subject.version, L5.version)) return null;
8508
+ if (subject.where !== void 0 && !line(subject.where, L5.where)) return null;
8509
8509
  }
8510
- if (call2.scenarios !== void 0 && (!Array.isArray(call2.scenarios) || call2.scenarios.length === 0 || call2.scenarios.length > L4.scenarios || !call2.scenarios.every((one) => line(one, L4.scenario)))) return null;
8510
+ if (call2.scenarios !== void 0 && (!Array.isArray(call2.scenarios) || call2.scenarios.length === 0 || call2.scenarios.length > L5.scenarios || !call2.scenarios.every((one) => line(one, L5.scenario)))) return null;
8511
8511
  review = {
8512
8512
  kind: "review",
8513
8513
  ...subject ? { subject: { name: subject.name, ...subject.version !== void 0 ? { version: subject.version } : {}, ...subject.where !== void 0 ? { where: subject.where } : {} } } : {},
@@ -29435,8 +29435,8 @@ async function adminOrgs(address2) {
29435
29435
  const owned = await gql(`query { entities(filter: {owner: {equalTo: ${JSON.stringify(address2)}}, type: {equalTo: "dao"}}, first: 50) { nodes { id } } }`, 30);
29436
29436
  const ids = owned.entities.nodes.map((node) => node.id);
29437
29437
  if (ids.length === 0) return [];
29438
- const iids = await gql(`query { iids(filter: {id: {in: ${JSON.stringify(ids)}}}) { nodes { id authentication verificationMethod } } }`, 30);
29439
- const admin = iids.iids.nodes.filter((iid) => canEditIid(iid, address2)).map((iid) => iid.id);
29438
+ const iids = await gql(`query { iids(filter: {id: {in: ${JSON.stringify(ids)}}}) { nodes { id authentication verificationMethod linkedResource } } }`, 30);
29439
+ const admin = iids.iids.nodes.filter((iid) => canEditIid(iid, address2) && !isAskEntity(iid)).map((iid) => iid.id);
29440
29440
  const names = await entityNames(admin).catch(() => /* @__PURE__ */ new Map());
29441
29441
  return admin.map((did4) => ({ did: did4, name: names.get(did4) ?? did4.slice(-8) }));
29442
29442
  }
@@ -29520,7 +29520,7 @@ function didWebDocUrl(value) {
29520
29520
  return null;
29521
29521
  }
29522
29522
  }
29523
- var ORG2, chainOracleIo, oracleRefusal;
29523
+ var ORG2, isAskEntity, chainOracleIo, oracleRefusal;
29524
29524
  var init_orgPayouts = __esm({
29525
29525
  "../../packages/openhands-sdk/src/data/orgPayouts.ts"() {
29526
29526
  "use strict";
@@ -29533,6 +29533,7 @@ var init_orgPayouts = __esm({
29533
29533
  init_payoutSettings();
29534
29534
  init_payoutTerms();
29535
29535
  ORG2 = /^did:ixo:entity:[0-9a-f]{32}$/;
29536
+ isAskEntity = (iid) => (iid.linkedResource ?? []).some((resource2) => /#(done|vct|rub)$/.test(resource2?.id ?? "") || resource2?.type === "DoneMeans");
29536
29537
  chainOracleIo = {
29537
29538
  entityType: async (did4) => (await gql(`query { entities(filter: {id: {equalTo: ${JSON.stringify(did4)}}}) { nodes { type } } }`, 0)).entities.nodes[0]?.type ?? null,
29538
29539
  fetchJson: (url4) => fetchPublicJson(url4, { timeoutMs: 5e3, revalidate: 0 })
@@ -39998,15 +39999,15 @@ function poly(field2, roots, create11, fft, length3) {
39998
39999
  };
39999
40000
  const checkLength = (a, b) => {
40000
40001
  checkPoly("a", a);
40001
- const L4 = a.length;
40002
+ const L5 = a.length;
40002
40003
  if (b !== void 0) {
40003
40004
  checkPoly("b", b);
40004
- if (b.length !== L4)
40005
- throw new Error(`poly: mismatched lengths ${L4} vs ${b.length}`);
40005
+ if (b.length !== L5)
40006
+ throw new Error(`poly: mismatched lengths ${L5} vs ${b.length}`);
40006
40007
  }
40007
- if (length3 !== void 0 && L4 !== length3)
40008
- throw new Error(`poly: expected fixed length ${length3}, got ${L4}`);
40009
- return L4;
40008
+ if (length3 !== void 0 && L5 !== length3)
40009
+ throw new Error(`poly: expected fixed length ${length3}, got ${L5}`);
40010
+ return L5;
40010
40011
  };
40011
40012
  function findOmegaIndex(x, n, brp = false, weights) {
40012
40013
  if (!isPowerOfTwo(n))
@@ -40161,11 +40162,11 @@ function poly(field2, roots, create11, fft, length3) {
40161
40162
  const idx = findOmegaIndex(x, a.length, brp);
40162
40163
  if (idx !== -1)
40163
40164
  return a[idx];
40164
- const L4 = this.basis(x, a.length, brp);
40165
+ const L5 = this.basis(x, a.length, brp);
40165
40166
  let acc = F.ZERO;
40166
40167
  for (let i = 0; i < a.length; i++)
40167
40168
  if (!F.is0(a[i]))
40168
- acc = F.add(acc, F.mul(a[i], L4[i]));
40169
+ acc = F.add(acc, F.mul(a[i], L5[i]));
40169
40170
  return acc;
40170
40171
  }
40171
40172
  },
@@ -40291,8 +40292,8 @@ function hash_to_field(msg, count2, options) {
40291
40292
  if (k < 0)
40292
40293
  throw new Error("hash_to_field: invalid k");
40293
40294
  const log2p = p.toString(2).length;
40294
- const L4 = Math.ceil((log2p + k) / 8);
40295
- const len_in_bytes = count2 * m * L4;
40295
+ const L5 = Math.ceil((log2p + k) / 8);
40296
+ const len_in_bytes = count2 * m * L5;
40296
40297
  let prb;
40297
40298
  if (expand2 === "xmd") {
40298
40299
  prb = expand_message_xmd(msg, DST, len_in_bytes, hash2);
@@ -40307,8 +40308,8 @@ function hash_to_field(msg, count2, options) {
40307
40308
  for (let i = 0; i < count2; i++) {
40308
40309
  const e = new Array(m);
40309
40310
  for (let j = 0; j < m; j++) {
40310
- const elm_offset = L4 * (j + i * m);
40311
- const tv = prb.subarray(elm_offset, elm_offset + L4);
40311
+ const elm_offset = L5 * (j + i * m);
40312
+ const tv = prb.subarray(elm_offset, elm_offset + L5);
40312
40313
  e[j] = mod2(os2ip(tv), p);
40313
40314
  }
40314
40315
  u[i] = e;
@@ -40650,18 +40651,18 @@ function createFROST(opts) {
40650
40651
  throw new Error("empty coefficients");
40651
40652
  return Poly.monomial.eval(coeffs, x);
40652
40653
  };
40653
- const deriveInterpolatingValue = (L4, xi) => {
40654
+ const deriveInterpolatingValue = (L5, xi) => {
40654
40655
  const err = "invalid parameters";
40655
- if (!L4.some((x) => Fn2.eql(x, xi)))
40656
+ if (!L5.some((x) => Fn2.eql(x, xi)))
40656
40657
  throw new Error(err);
40657
- const Lset = new Set(L4);
40658
- if (Lset.size !== L4.length)
40658
+ const Lset = new Set(L5);
40659
+ if (Lset.size !== L5.length)
40659
40660
  throw new Error(err);
40660
40661
  if (!Lset.has(xi))
40661
40662
  throw new Error(err);
40662
40663
  let num5 = Fn2.ONE;
40663
40664
  let den = Fn2.ONE;
40664
- for (const x of L4) {
40665
+ for (const x of L5) {
40665
40666
  if (Fn2.eql(x, xi))
40666
40667
  continue;
40667
40668
  num5 = Fn2.mul(num5, x);
@@ -42744,9 +42745,9 @@ var init_legacy = __esm({
42744
42745
  Id160 = /* @__PURE__ */ (() => Uint8Array.from(new Array(16).fill(0).map((_, i) => i)))();
42745
42746
  Pi160 = /* @__PURE__ */ (() => Id160.map((i) => (9 * i + 5) % 16))();
42746
42747
  idxLR = /* @__PURE__ */ (() => {
42747
- const L4 = [Id160];
42748
+ const L5 = [Id160];
42748
42749
  const R = [Pi160];
42749
- const res = [L4, R];
42750
+ const res = [L5, R];
42750
42751
  for (let i = 0; i < 4; i++)
42751
42752
  for (let j of res)
42752
42753
  j.push(j[i].map((k) => Rho160[k]));
@@ -43182,9 +43183,9 @@ function weierstrass(params, extraOpts = {}) {
43182
43183
  y = Fp2.neg(y);
43183
43184
  return { x, y };
43184
43185
  } else if (length3 === uncomp && head === 4) {
43185
- const L4 = Fp2.BYTES;
43186
- const x = Fp2.fromBytes(tail.subarray(0, L4));
43187
- const y = Fp2.fromBytes(tail.subarray(L4, L4 * 2));
43186
+ const L5 = Fp2.BYTES;
43187
+ const x = Fp2.fromBytes(tail.subarray(0, L5));
43188
+ const y = Fp2.fromBytes(tail.subarray(L5, L5 * 2));
43188
43189
  if (!isValidXY(x, y))
43189
43190
  throw new Error("bad point: is not on curve");
43190
43191
  return { x, y };
@@ -43709,9 +43710,9 @@ function ecdsa(Point2, hash2, ecdsaOpts = {}) {
43709
43710
  format11 = "compact";
43710
43711
  bytes3 = bytes3.subarray(1);
43711
43712
  }
43712
- const L4 = lengths.signature / 2;
43713
- const r = bytes3.subarray(0, L4);
43714
- const s = bytes3.subarray(L4, L4 * 2);
43713
+ const L5 = lengths.signature / 2;
43714
+ const r = bytes3.subarray(0, L5);
43715
+ const s = bytes3.subarray(L5, L5 * 2);
43715
43716
  return new Signature3(Fn2.fromBytes(r), Fn2.fromBytes(s), recid);
43716
43717
  }
43717
43718
  static fromHex(hex5, format11) {
@@ -113022,15 +113023,15 @@ var require_xstream = __commonJS({
113022
113023
  Merge2.prototype._start = function(out) {
113023
113024
  this.out = out;
113024
113025
  var s = this.insArr;
113025
- var L4 = s.length;
113026
- this.ac = L4;
113027
- for (var i = 0; i < L4; i++)
113026
+ var L5 = s.length;
113027
+ this.ac = L5;
113028
+ for (var i = 0; i < L5; i++)
113028
113029
  s[i]._add(this);
113029
113030
  };
113030
113031
  Merge2.prototype._stop = function() {
113031
113032
  var s = this.insArr;
113032
- var L4 = s.length;
113033
- for (var i = 0; i < L4; i++)
113033
+ var L5 = s.length;
113034
+ for (var i = 0; i < L5; i++)
113034
113035
  s[i]._remove(this);
113035
113036
  this.out = NO;
113036
113037
  };
@@ -113763,16 +113764,16 @@ var require_xstream = __commonJS({
113763
113764
  }
113764
113765
  Stream2.prototype._n = function(t) {
113765
113766
  var a = this._ils;
113766
- var L4 = a.length;
113767
+ var L5 = a.length;
113767
113768
  if (this._d)
113768
113769
  this._dl._n(t);
113769
- if (L4 == 1)
113770
+ if (L5 == 1)
113770
113771
  a[0]._n(t);
113771
- else if (L4 == 0)
113772
+ else if (L5 == 0)
113772
113773
  return;
113773
113774
  else {
113774
113775
  var b = cp(a);
113775
- for (var i = 0; i < L4; i++)
113776
+ for (var i = 0; i < L5; i++)
113776
113777
  b[i]._n(t);
113777
113778
  }
113778
113779
  };
@@ -113781,35 +113782,35 @@ var require_xstream = __commonJS({
113781
113782
  return;
113782
113783
  this._err = err;
113783
113784
  var a = this._ils;
113784
- var L4 = a.length;
113785
+ var L5 = a.length;
113785
113786
  this._x();
113786
113787
  if (this._d)
113787
113788
  this._dl._e(err);
113788
- if (L4 == 1)
113789
+ if (L5 == 1)
113789
113790
  a[0]._e(err);
113790
- else if (L4 == 0)
113791
+ else if (L5 == 0)
113791
113792
  return;
113792
113793
  else {
113793
113794
  var b = cp(a);
113794
- for (var i = 0; i < L4; i++)
113795
+ for (var i = 0; i < L5; i++)
113795
113796
  b[i]._e(err);
113796
113797
  }
113797
- if (!this._d && L4 == 0)
113798
+ if (!this._d && L5 == 0)
113798
113799
  throw this._err;
113799
113800
  };
113800
113801
  Stream2.prototype._c = function() {
113801
113802
  var a = this._ils;
113802
- var L4 = a.length;
113803
+ var L5 = a.length;
113803
113804
  this._x();
113804
113805
  if (this._d)
113805
113806
  this._dl._c();
113806
- if (L4 == 1)
113807
+ if (L5 == 1)
113807
113808
  a[0]._c();
113808
- else if (L4 == 0)
113809
+ else if (L5 == 0)
113809
113810
  return;
113810
113811
  else {
113811
113812
  var b = cp(a);
113812
- for (var i = 0; i < L4; i++)
113813
+ for (var i = 0; i < L5; i++)
113813
113814
  b[i]._c();
113814
113815
  }
113815
113816
  };
@@ -261315,7 +261316,8 @@ function prepareAsk(poster, entityDid, adminAccount, terms, now3 = Date.now(), s
261315
261316
  const checkReward = terms.checker && terms.checkRewardUixo ? BigInt(terms.checkRewardUixo) : 0n;
261316
261317
  const spots = BigInt(Math.max(1, terms.quota));
261317
261318
  const denom = terms.denom ?? askDenom();
261318
- if (denom === "upay" && !offChain && !card && network() === "mainnet" && askDenom() !== "upay") throw new Error("PAY is not a reward coin on mainnet: post the reward in USDC");
261319
+ const review = terms.rules?.call?.kind === "review";
261320
+ if (denom === "upay" && !offChain && !card && !review && network() === "mainnet" && askDenom() !== "upay") throw new Error("PAY is not a reward coin on mainnet: post the reward in USDC");
261319
261321
  const feeDenom = terms.feeDenom ?? checkerFeeDenom(network());
261320
261322
  const rewardEscrow = offChain || card ? 0n : BigInt(terms.amountUixo) * spots;
261321
261323
  const feeEscrow = card && feeDenom === "upay" ? 0n : checkReward * spots;
@@ -263504,6 +263506,210 @@ var init_callChecks = __esm({
263504
263506
  }
263505
263507
  });
263506
263508
 
263509
+ // src/callTerms.ts
263510
+ function stepsFromMermaid(source) {
263511
+ const order2 = [];
263512
+ const labels = /* @__PURE__ */ new Map();
263513
+ const node = /([A-Za-z0-9_]+)\s*(?:\[\(?"?([^\]"]+)"?\)?\]|\(\(?"?([^)"]+)"?\)?\)|\{"?([^}"]+)"?\})?/y;
263514
+ const seen2 = (raw) => {
263515
+ node.lastIndex = 0;
263516
+ const match6 = node.exec(raw.trim());
263517
+ if (!match6) return;
263518
+ const id = match6[1];
263519
+ const label = (match6[2] ?? match6[3] ?? match6[4])?.trim();
263520
+ if (label && !labels.has(id)) labels.set(id, label);
263521
+ if (!order2.includes(id)) order2.push(id);
263522
+ };
263523
+ for (const line2 of source.split("\n")) {
263524
+ if (!/--+>|==+>|-\.->/.test(line2)) continue;
263525
+ const parts = line2.replace(/\|[^|]*\|/g, " ").split(/\s*(?:--+>|==+>|-\.->)\s*/);
263526
+ for (const part of parts) if (part.trim() && !/^(flowchart|graph)\b/i.test(part.trim())) seen2(part);
263527
+ }
263528
+ return order2.map((id) => ({ title: (labels.get(id) ?? id).slice(0, L2.stepTitle) }));
263529
+ }
263530
+ function callChecker(network2, review, deployment2) {
263531
+ const asky = review ? askyChecker(network2) : null;
263532
+ return asky ? { address: asky.address, at: { url: asky.url }, name: ASKY_CHECKER_NAME, fee: asky.fee } : { address: deployment2, at: null, name: null, fee: null };
263533
+ }
263534
+ function missingOf(fields, ctx) {
263535
+ const out = [];
263536
+ const review = fields.kind === "review";
263537
+ if (review && !fields.sponsor)
263538
+ out.push({
263539
+ field: "sponsor",
263540
+ question: `Which marketplace verifies the pros? ${ctx.marketplaces ? `On asks.world today: ${ctx.marketplaces}.` : "list_marketplaces names them."} The pros you invite come from its roster, and it earns the marketplace's share of each approved report. Ask the person, even when there is one.`,
263541
+ example: '"ixo"'
263542
+ });
263543
+ if (!fields.title) out.push({ field: "title", question: review ? "What is being reviewed, as one sentence a pro reads first?" : "What is the call, in one sentence?", example: review ? "Try Qi Portal 2.3 as a first-time project owner and tell us where it fails" : "How should a city pay strangers to fix what they find?" });
263544
+ if (review && !fields.subject) out.push({ field: "subject", question: "What is reviewed: its name, the version to test, and where a pro finds it (a public address). Put test accounts and anything private in the invitation, not here: the pro ask is readable by everyone on its list.", example: '{ "name": "Qi Portal", "version": "2.3.0", "where": "https://staging.qi.space" }' });
263545
+ if (review && !fields.scenarios?.length) out.push({ field: "scenarios", question: "The scenarios to try, one line each, up to eight: the tasks a real user comes to do. Every report must cover each with a step.", example: '["Sign up with the invite link on a phone that has never seen the app", "Create a project and add two members", "Export the project and open it on a laptop"]' });
263546
+ if (!fields.mode && !review)
263547
+ out.push({
263548
+ field: "mode",
263549
+ question: "A competition, or a hire? A competition has a pick and runners-up beside the paid entries. A hire pays every entry that passes the lines the same, up to a number, and picks nobody: hiring five pros at 20 each is a hire.",
263550
+ example: '"hire"'
263551
+ });
263552
+ if (!fields.lede) out.push({ field: "lede", question: "Two or three sentences under the title: what you want and why.", example: "We want one page on a rule a city could actually run. The pick runs on the network for a month." });
263553
+ if (!fields.brief?.length)
263554
+ out.push({ field: "brief", question: "The story, up to eight short paragraphs: what you are asking for, what good looks like, what happens to the pick.", example: '["What we are asking for\u2026", "What good looks like\u2026", "What happens to the pick\u2026"]' });
263555
+ if (linesOf(fields)?.length !== L2.lines)
263556
+ out.push({
263557
+ field: "lines",
263558
+ question: 'The five requirements the jury reviews. Each is a must a good entry passes ("text"), and what fails it ("fail"), written as the end of the sentence "Fail this only if \u2026" \u2014 a clause, not a sentence of its own. An entry must pass all five to be paid.',
263559
+ example: '[{ "text": "It puts a price on one fix", "fail": "there is no number" }, \u2026five in all]'
263560
+ });
263561
+ if (!fields.money)
263562
+ out.push(
263563
+ review ? {
263564
+ field: "money",
263565
+ question: `What each pro receives for a report that passes the lines, and how many reports you will pay for (one per pro). In dollars.${ctx.holds ? ` You hold ${ctx.holds}.` : ""}`,
263566
+ example: '{ "entry_each": 120, "entry_up_to": 3 }'
263567
+ } : fields.mode === "hire" ? {
263568
+ field: "money",
263569
+ question: `What each entry that passes earns, and up to how many entries you will pay for. In dollars.${ctx.holds ? ` You hold ${ctx.holds}.` : ""}`,
263570
+ example: '{ "entry_each": 20, "entry_up_to": 5 }'
263571
+ } : {
263572
+ field: "money",
263573
+ question: `The prize for the pick; runners-up, how many and what each gets; what every entry that passes earns, and up to how many. In dollars.${ctx.holds ? ` You hold ${ctx.holds}.` : ""}`,
263574
+ example: '{ "prize": 2, "runners_n": 2, "runners_each": 0.5, "entry_each": 0.2, "entry_up_to": 5 }'
263575
+ }
263576
+ );
263577
+ if (!fields.openDays)
263578
+ out.push(
263579
+ fields.mode === "hire" ? { field: "open_days", question: "How many days the call takes entries, 1 to 30. Every passing entry is paid as it is judged; nothing waits for a pick.", example: "7" } : { field: "open_days", question: "How many days the call stays open, 1 to 30. The shortlist shows the day after it closes; you pick three days later.", example: "7" }
263580
+ );
263581
+ if (!review && !fields.access)
263582
+ out.push({
263583
+ field: "access",
263584
+ question: `Who may enter? "public": anyone, listed on the board. "apply": listed, but people apply and you say yes to each before they can enter. "invite": not listed; only people you invite, by address, by their page's @handle, or with a link that admits one new person each.`,
263585
+ example: '"invite"'
263586
+ });
263587
+ if (!review && fields.access === "invite" && !fields.invite?.length)
263588
+ out.push({ field: "invite", question: 'Who to invite: ixo1 addresses, @handles of people with a page, and "link" once per single-use link to mint. You can add more later with invite_to_call. Access details they need (a staging address, a test account) go in invite_note, which only the people invited read.', example: '["link", "link", "@ana"]' });
263589
+ if (!fields.start && !review)
263590
+ out.push({
263591
+ field: "start",
263592
+ question: "The first message an entrant should paste into their AI. Offer this one unless they want their own.",
263593
+ example: `Read the open call "${fields.title ?? "\u2026"}" on asks.world with read_ask, then help me write one page in my own words that addresses all five requirements. Ask me what I know first; file it with submit_work only when I say so.`
263594
+ });
263595
+ return out;
263596
+ }
263597
+ function optionalOf(fields, site) {
263598
+ const samples = `${site}/opencall/samples`;
263599
+ const out = [];
263600
+ if (!fields.cover) out.push(`cover: { url, alt, caption? } \u2014 a picture that heads the call. None yet; a drawn sample: ${samples}/cover.svg`);
263601
+ if (!fields.pictures?.length) out.push(`pictures: up to 6 of { url, alt, caption? } \u2014 what good looks like. Drawn samples: ${samples}/lamp.svg, ${samples}/lane.svg, ${samples}/drain.svg`);
263602
+ if (!fields.diagram) out.push("diagram: { title, source } \u2014 a mermaid flowchart; its A --> B lines become numbered steps");
263603
+ if (!fields.data) out.push("data: { title, csv, note? } \u2014 up to 4,000 characters of CSV; the first number column is drawn as bars");
263604
+ if (!fields.files?.length) out.push("files: up to 6 of { url, name, note? } \u2014 what to read first");
263605
+ if (!fields.poster) out.push("poster: how you want to be named on the call (default: the account it posts as)");
263606
+ return out;
263607
+ }
263608
+ function blocksOf(fields) {
263609
+ const blocks = [];
263610
+ if (fields.cover) blocks.push({ kind: "cover", ...fields.cover });
263611
+ if (fields.brief?.length) blocks.push({ kind: "story", paragraphs: fields.brief });
263612
+ if (fields.pictures?.length) blocks.push({ kind: "pictures", items: fields.pictures });
263613
+ if (fields.diagram) blocks.push({ kind: "diagram", title: fields.diagram.title, steps: stepsFromMermaid(fields.diagram.source), source: fields.diagram.source });
263614
+ if (fields.data) blocks.push({ kind: "data", ...fields.data });
263615
+ if (fields.files?.length) blocks.push({ kind: "files", items: fields.files });
263616
+ if (fields.start) blocks.push({ kind: "start", prompt: fields.start });
263617
+ else if (fields.kind === "review") blocks.push({ kind: "start", prompt: reviewStart(fields.title) });
263618
+ return blocks;
263619
+ }
263620
+ function callOfDraft(draft, poster, dates, legs, share, sponsor) {
263621
+ const f = draft.fields;
263622
+ if (!isReady(f) || !f.money) throw new Error("the draft is not ready to post");
263623
+ return {
263624
+ slug: draft.slug,
263625
+ ...f.mode === "hire" ? { mode: "hire" } : {},
263626
+ ...f.kind === "review" ? { kind: "review", ...f.subject ? { subject: f.subject } : {}, ...f.scenarios?.length ? { scenarios: f.scenarios } : {} } : {},
263627
+ title: f.title,
263628
+ lede: f.lede,
263629
+ poster: f.poster ?? poster,
263630
+ points: linesOf(f).map(() => 100 / L2.lines),
263631
+ money: f.mode === "hire" ? { ...f.money, prize: 0, runnersN: 0, runnersEach: 0 } : f.money,
263632
+ ...share ? { share: { network: share.network, node: share.node } } : {},
263633
+ ...sponsor ? { sponsor: { slug: sponsor.slug, name: sponsor.name, node: sponsor.node } } : {},
263634
+ ...dates,
263635
+ ...legs && Object.keys(legs).length ? { legs } : {},
263636
+ blocks: blocksOf(f)
263637
+ };
263638
+ }
263639
+ function legPlan(fields, leg, checkBase, share, feeInReward = false) {
263640
+ const m = fields.money;
263641
+ const priced = (payBase) => {
263642
+ const legBase = share ? grossFor(payBase, share) : payBase;
263643
+ return { payBase, legBase, shareBase: legBase - payBase };
263644
+ };
263645
+ if (leg === "entries") {
263646
+ const pay2 = priced(toBase2(m.entryEach));
263647
+ if (feeInReward) return { leg, ...pay2, quota: m.entryUpTo, escrowSpots: m.entryUpTo, checkBase, escrowBase: (pay2.legBase + checkBase) * m.entryUpTo, feeBase: 0 };
263648
+ return { leg, ...pay2, quota: m.entryUpTo, escrowSpots: m.entryUpTo, checkBase, escrowBase: pay2.legBase * m.entryUpTo, feeBase: checkBase * m.entryUpTo };
263649
+ }
263650
+ const winners = leg === "prize" ? 1 : m.runnersN;
263651
+ const pay = priced(toBase2(leg === "prize" ? m.prize : m.runnersEach));
263652
+ return { leg, ...pay, quota: pickQuota(winners), escrowSpots: winners, checkBase: 0, escrowBase: pay.legBase * winners, feeBase: 0 };
263653
+ }
263654
+ function callShare(fields, split3) {
263655
+ if (!callShares(fields)) return { share: null };
263656
+ return split3 ? { share: { network: split3.network, node: split3.node } } : { unread: true };
263657
+ }
263658
+ function legTerms(draft, leg, ctx) {
263659
+ const access2 = accessOf(draft.fields);
263660
+ if (leg === "entries") {
263661
+ const legs = { ...draft.posted.prize ? { prize: draft.posted.prize.id } : {}, ...draft.posted.runnersUp ? { runnersUp: draft.posted.runnersUp.id } : {} };
263662
+ const review = draft.fields.kind === "review";
263663
+ return {
263664
+ ...callEntriesTerms({
263665
+ call: callOfDraft(draft, ctx.poster, ctx.dates, legs, ctx.share, ctx.sponsor),
263666
+ lines: linesOf(draft.fields),
263667
+ judge: ctx.oracle,
263668
+ access: access2,
263669
+ ...review ? { report: draft.fields.report ?? [] } : {},
263670
+ ...review && ctx.approver ? { approver: ctx.approver } : {}
263671
+ }),
263672
+ via: "mcp"
263673
+ };
263674
+ }
263675
+ return { ...callPickTerms({ call: callOfDraft(draft, ctx.poster, ctx.dates, void 0, ctx.share, ctx.sponsor), leg, access: access2 }), via: "mcp" };
263676
+ }
263677
+ function callPlan(draft, ctx, now3 = Date.now()) {
263678
+ if (callShares(draft.fields) !== Boolean(ctx.share)) throw new Error(ctx.share ? "only a private call carries the network's share" : "a private call is priced with the network's share: read the split first (callShare)");
263679
+ const dates = draft.dates ?? callDates(draft.fields.openDays, now3, draft.fields.mode === "hire" ? "hire" : void 0);
263680
+ const entries2 = legTerms(draft, "entries", { poster: ctx.poster, dates, oracle: { kind: "oracle", address: ctx.oracle }, share: ctx.share, sponsor: ctx.sponsor });
263681
+ const checkBase = ctx.checkerLegBase(entries2);
263682
+ const legs = legOrder(draft.fields).map((leg) => legPlan(draft.fields, leg, checkBase, ctx.share, ctx.feeInReward));
263683
+ return { legs, totalBase: legs.reduce((sum, one) => sum + one.escrowBase, 0), dates, share: ctx.share };
263684
+ }
263685
+ var L2, MICRO4, linesOf, nudgeAtFor, reviewStart, isReady, legOrder, accessOf, nextLeg, toBase2, callShares, SHARE_UNREAD;
263686
+ var init_callTerms = __esm({
263687
+ "src/callTerms.ts"() {
263688
+ "use strict";
263689
+ init_call();
263690
+ init_terms();
263691
+ init_checkers();
263692
+ L2 = CALL_LIMITS;
263693
+ MICRO4 = 1e6;
263694
+ linesOf = (fields) => fields.lines ?? (fields.kind === "review" ? [...REVIEW_LINES] : void 0);
263695
+ nudgeAtFor = (network2, judge) => {
263696
+ const asky = askyChecker(network2);
263697
+ return asky && judge === asky.address ? { url: asky.url } : null;
263698
+ };
263699
+ reviewStart = (title) => (
263700
+ /* The person copies this into their agent, so it is in their words: no tool names (expert prompts review, 2.6). */
263701
+ `I'm taking part in the review "${title ?? "\u2026"}" on pro.asks.world. Show me what the review asks for, then help me try each scenario and keep notes and screenshots as I go: what I did, what I expected and what I saw. Write up my findings with me, each with how serious it is and how to reproduce it, and my recommendations. Show me all of it, and hand it in as my report only when I say so.`
263702
+ );
263703
+ isReady = (fields) => missingOf(fields, { symbol: "", holds: null }).length === 0;
263704
+ legOrder = (fields) => legsOf({ mode: fields.mode === "hire" ? "hire" : void 0, money: fields.money ?? { prize: 0, runnersN: 0, runnersEach: 0, entryEach: 0, entryUpTo: 0 } });
263705
+ accessOf = (fields) => fields.access === "apply" || fields.access === "invite" ? fields.access : void 0;
263706
+ nextLeg = (draft) => legOrder(draft.fields).find((leg) => !draft.posted[leg]) ?? null;
263707
+ toBase2 = (display) => Math.round(display * MICRO4);
263708
+ callShares = (fields) => sharedCall({ access: accessOf(fields), call: { kind: fields.kind } });
263709
+ SHARE_UNREAD = "Refused: this call is a hire by invitation or application, which carries the network's share, and the fee split could not be read just now, so its leg cannot be priced. Nothing was posted. Try again in a minute.";
263710
+ }
263711
+ });
263712
+
263507
263713
  // ../../packages/openhands-sdk/src/rubric/feeLine.ts
263508
263714
  var feeLine_exports = {};
263509
263715
  __export(feeLine_exports, {
@@ -263758,26 +263964,6 @@ function doorOf(access2, invite) {
263758
263964
  if (access2 === "invite" && items.length === 0) return { refused: 'access "invite" needs invite: ixo1 addresses, @handles of people with a page, and "link" once per single-use link' };
263759
263965
  return access2 === "apply" || access2 === "invite" ? { access: access2, invite: items } : { invite: items };
263760
263966
  }
263761
- function stepsFromMermaid(source) {
263762
- const order2 = [];
263763
- const labels = /* @__PURE__ */ new Map();
263764
- const node = /([A-Za-z0-9_]+)\s*(?:\[\(?"?([^\]"]+)"?\)?\]|\(\(?"?([^)"]+)"?\)?\)|\{"?([^}"]+)"?\})?/y;
263765
- const seen2 = (raw) => {
263766
- node.lastIndex = 0;
263767
- const match6 = node.exec(raw.trim());
263768
- if (!match6) return;
263769
- const id = match6[1];
263770
- const label = (match6[2] ?? match6[3] ?? match6[4])?.trim();
263771
- if (label && !labels.has(id)) labels.set(id, label);
263772
- if (!order2.includes(id)) order2.push(id);
263773
- };
263774
- for (const line2 of source.split("\n")) {
263775
- if (!/--+>|==+>|-\.->/.test(line2)) continue;
263776
- const parts = line2.replace(/\|[^|]*\|/g, " ").split(/\s*(?:--+>|==+>|-\.->)\s*/);
263777
- for (const part of parts) if (part.trim() && !/^(flowchart|graph)\b/i.test(part.trim())) seen2(part);
263778
- }
263779
- return order2.map((id) => ({ title: (labels.get(id) ?? id).slice(0, L2.stepTitle) }));
263780
- }
263781
263967
  function typedText(input) {
263782
263968
  const out = [];
263783
263969
  const push = (value) => {
@@ -263830,20 +264016,20 @@ function mergeDraft(draft, input, now3 = /* @__PURE__ */ new Date()) {
263830
264016
  if (problem) refused2.push(problem);
263831
264017
  else fields[key] = value;
263832
264018
  };
263833
- if (input.title !== void 0) take("title", oneLine(input.title), within(oneLine(input.title), L2.title, "The title"));
263834
- if (input.lede !== void 0) take("lede", oneLine(input.lede), within(oneLine(input.lede), L2.lede, "The lede"));
263835
- if (input.poster !== void 0) take("poster", oneLine(input.poster), within(oneLine(input.poster), L2.poster, "The poster's name"));
264019
+ if (input.title !== void 0) take("title", oneLine(input.title), within(oneLine(input.title), L3.title, "The title"));
264020
+ if (input.lede !== void 0) take("lede", oneLine(input.lede), within(oneLine(input.lede), L3.lede, "The lede"));
264021
+ if (input.poster !== void 0) take("poster", oneLine(input.poster), within(oneLine(input.poster), L3.poster, "The poster's name"));
263836
264022
  if (input.brief !== void 0) {
263837
264023
  const paragraphs = input.brief.map(oneLine).filter(Boolean);
263838
264024
  take(
263839
264025
  "brief",
263840
264026
  paragraphs,
263841
- paragraphs.length === 0 ? "The brief has no paragraphs" : paragraphs.length > L2.paragraphs ? `The brief is ${paragraphs.length} paragraphs; the most is ${L2.paragraphs}` : paragraphs.map((one, index) => within(one, L2.paragraph, `Paragraph ${index + 1}`)).find(Boolean) ?? null
264027
+ paragraphs.length === 0 ? "The brief has no paragraphs" : paragraphs.length > L3.paragraphs ? `The brief is ${paragraphs.length} paragraphs; the most is ${L3.paragraphs}` : paragraphs.map((one, index) => within(one, L3.paragraph, `Paragraph ${index + 1}`)).find(Boolean) ?? null
263842
264028
  );
263843
264029
  }
263844
264030
  if (input.lines !== void 0) {
263845
264031
  const lines2 = input.lines.map((one) => ({ text: oneLine(one.text), ...one.fail?.trim() ? { fail: oneLine(one.fail) } : {} }));
263846
- let problem = lines2.length !== L2.lines ? `The jury rules on exactly ${L2.lines} lines; ${lines2.length} were given` : null;
264032
+ let problem = lines2.length !== L3.lines ? `The jury rules on exactly ${L3.lines} lines; ${lines2.length} were given` : null;
263847
264033
  if (!problem) {
263848
264034
  for (const [index, line2] of lines2.entries()) {
263849
264035
  try {
@@ -263867,11 +264053,11 @@ function mergeDraft(draft, input, now3 = /* @__PURE__ */ new Date()) {
263867
264053
  }
263868
264054
  if (input.subject !== void 0) {
263869
264055
  const subject = { name: oneLine(input.subject.name), ...input.subject.version?.trim() ? { version: oneLine(input.subject.version) } : {}, ...input.subject.where?.trim() ? { where: oneLine(input.subject.where) } : {} };
263870
- take("subject", subject, within(subject.name, L2.subjectName, "What is reviewed") ?? (subject.version ? within(subject.version, L2.version, "The version") : null) ?? (subject.where ? within(subject.where, L2.where, "Where it is") : null));
264056
+ take("subject", subject, within(subject.name, L3.subjectName, "What is reviewed") ?? (subject.version ? within(subject.version, L3.version, "The version") : null) ?? (subject.where ? within(subject.where, L3.where, "Where it is") : null));
263871
264057
  }
263872
264058
  if (input.scenarios !== void 0) {
263873
264059
  const scenarios = input.scenarios.map(oneLine).filter(Boolean);
263874
- take("scenarios", scenarios, scenarios.length === 0 ? "No scenarios" : scenarios.length > L2.scenarios ? `${scenarios.length} scenarios; the most is ${L2.scenarios}` : scenarios.map((one, index) => within(one, L2.scenario, `Scenario ${index + 1}`)).find(Boolean) ?? null);
264060
+ take("scenarios", scenarios, scenarios.length === 0 ? "No scenarios" : scenarios.length > L3.scenarios ? `${scenarios.length} scenarios; the most is ${L3.scenarios}` : scenarios.map((one, index) => within(one, L3.scenario, `Scenario ${index + 1}`)).find(Boolean) ?? null);
263875
264061
  }
263876
264062
  if (input.report !== void 0) {
263877
264063
  const sections = [...new Set(input.report.map(oneLine).filter(Boolean))];
@@ -263895,19 +264081,19 @@ function mergeDraft(draft, input, now3 = /* @__PURE__ */ new Date()) {
263895
264081
  const runnersN = m.runners_n ?? 0;
263896
264082
  const runnersEach = m.runners_each ?? 0;
263897
264083
  const money2 = { prize, runnersN, runnersEach, entryEach: m.entry_each, entryUpTo: m.entry_up_to };
263898
- const problem = hire && (prize > 0 || runnersN > 0) ? 'A hire has no prize and no runners-up: every entry that passes is paid the same. Say mode: "competition" for a pick' : !hire && !(prize > 0) ? 'The prize must be more than nothing (or make it a hire: mode "hire", no prize)' : !Number.isInteger(runnersN) || runnersN < 0 || runnersN > 5 ? "Runners-up are 0 to 5" : runnersN > 0 && !(runnersEach > 0) ? "Each runner-up must get something" : !(m.entry_each > 0) ? "An entry that passes must earn something" : !Number.isInteger(m.entry_up_to) || m.entry_up_to < 1 || m.entry_up_to > ENTRIES_MAX ? `Entries paid are 1 to ${ENTRIES_MAX} on this build` : [prize, runnersEach, m.entry_each].some((one) => Math.abs(one * MICRO4 - Math.round(one * MICRO4)) > 1e-6) ? "Amounts go to six decimals at most" : null;
264084
+ const problem = hire && (prize > 0 || runnersN > 0) ? 'A hire has no prize and no runners-up: every entry that passes is paid the same. Say mode: "competition" for a pick' : !hire && !(prize > 0) ? 'The prize must be more than nothing (or make it a hire: mode "hire", no prize)' : !Number.isInteger(runnersN) || runnersN < 0 || runnersN > 5 ? "Runners-up are 0 to 5" : runnersN > 0 && !(runnersEach > 0) ? "Each runner-up must get something" : !(m.entry_each > 0) ? "An entry that passes must earn something" : !Number.isInteger(m.entry_up_to) || m.entry_up_to < 1 || m.entry_up_to > ENTRIES_MAX ? `Entries paid are 1 to ${ENTRIES_MAX} on this build` : [prize, runnersEach, m.entry_each].some((one) => Math.abs(one * MICRO5 - Math.round(one * MICRO5)) > 1e-6) ? "Amounts go to six decimals at most" : null;
263899
264085
  take("money", money2.runnersN === 0 ? { ...money2, runnersEach: 0 } : money2, problem);
263900
264086
  if (!problem && fields.mode === void 0) fields.mode = hire ? "hire" : "competition";
263901
264087
  }
263902
264088
  if (input.open_days !== void 0) take("openDays", input.open_days, Number.isInteger(input.open_days) && input.open_days >= 1 && input.open_days <= 30 ? null : "A call stays open 1 to 30 days");
263903
- if (input.start !== void 0) take("start", manyLines(input.start), within(manyLines(input.start), L2.start, "The first message", true));
264089
+ if (input.start !== void 0) take("start", manyLines(input.start), within(manyLines(input.start), L3.start, "The first message", true));
263904
264090
  if (input.cover !== void 0) {
263905
264091
  if (input.cover === null) fields.cover = null;
263906
264092
  else take("cover", { url: input.cover.url.trim(), alt: oneLine(input.cover.alt), ...input.cover.caption?.trim() ? { caption: oneLine(input.cover.caption) } : {} }, picture({ ...input.cover, url: input.cover.url.trim() }, "The cover"));
263907
264093
  }
263908
264094
  if (input.pictures !== void 0) {
263909
264095
  const items = input.pictures.map((one) => ({ url: one.url.trim(), alt: oneLine(one.alt), ...one.caption?.trim() ? { caption: oneLine(one.caption) } : {} }));
263910
- take("pictures", items, items.length > L2.items ? `${items.length} pictures; the most is ${L2.items}` : items.map((one, index) => picture(one, `Picture ${index + 1}`)).find(Boolean) ?? null);
264096
+ take("pictures", items, items.length > L3.items ? `${items.length} pictures; the most is ${L3.items}` : items.map((one, index) => picture(one, `Picture ${index + 1}`)).find(Boolean) ?? null);
263911
264097
  }
263912
264098
  if (input.diagram !== void 0) {
263913
264099
  if (input.diagram === null) fields.diagram = null;
@@ -263917,7 +264103,7 @@ function mergeDraft(draft, input, now3 = /* @__PURE__ */ new Date()) {
263917
264103
  take(
263918
264104
  "diagram",
263919
264105
  { title: oneLine(input.diagram.title), source },
263920
- within(oneLine(input.diagram.title), L2.title, "The diagram's title") ?? within(source, L2.source, "The diagram's source", true) ?? (steps.length === 0 ? 'The diagram has no "A --> B" lines to draw steps from' : steps.length > L2.steps ? `The diagram has ${steps.length} steps; the page draws ${L2.steps} at most` : null)
264106
+ within(oneLine(input.diagram.title), L3.title, "The diagram's title") ?? within(source, L3.source, "The diagram's source", true) ?? (steps.length === 0 ? 'The diagram has no "A --> B" lines to draw steps from' : steps.length > L3.steps ? `The diagram has ${steps.length} steps; the page draws ${L3.steps} at most` : null)
263921
264107
  );
263922
264108
  }
263923
264109
  }
@@ -263925,7 +264111,7 @@ function mergeDraft(draft, input, now3 = /* @__PURE__ */ new Date()) {
263925
264111
  if (input.data === null) fields.data = null;
263926
264112
  else {
263927
264113
  const csv = manyLines(input.data.csv);
263928
- take("data", { title: oneLine(input.data.title), csv, ...input.data.note?.trim() ? { note: oneLine(input.data.note) } : {} }, within(oneLine(input.data.title), L2.title, "The data's title") ?? within(csv, L2.csv, "The CSV", true));
264114
+ take("data", { title: oneLine(input.data.title), csv, ...input.data.note?.trim() ? { note: oneLine(input.data.note) } : {} }, within(oneLine(input.data.title), L3.title, "The data's title") ?? within(csv, L3.csv, "The CSV", true));
263929
264115
  }
263930
264116
  }
263931
264117
  if (input.files !== void 0) {
@@ -263933,166 +264119,11 @@ function mergeDraft(draft, input, now3 = /* @__PURE__ */ new Date()) {
263933
264119
  take(
263934
264120
  "files",
263935
264121
  items,
263936
- items.length > L2.items ? `${items.length} files; the most is ${L2.items}` : items.map((one, index) => !isHttps2(one.url) ? `File ${index + 1}: "${one.url.slice(0, 80)}" is not an https address` : within(one.name, L2.name, `File ${index + 1}'s name`)).find(Boolean) ?? null
264122
+ items.length > L3.items ? `${items.length} files; the most is ${L3.items}` : items.map((one, index) => !isHttps2(one.url) ? `File ${index + 1}: "${one.url.slice(0, 80)}" is not an https address` : within(one.name, L3.name, `File ${index + 1}'s name`)).find(Boolean) ?? null
263937
264123
  );
263938
264124
  }
263939
264125
  return { draft: { ...draft, fields, updatedAt: now3.toISOString() }, refused: refused2 };
263940
264126
  }
263941
- function callChecker(network2, review, deployment2) {
263942
- const asky = review ? askyChecker(network2) : null;
263943
- return asky ? { address: asky.address, at: { url: asky.url }, name: ASKY_CHECKER_NAME, fee: asky.fee } : { address: deployment2, at: null, name: null, fee: null };
263944
- }
263945
- function missingOf(fields, ctx) {
263946
- const out = [];
263947
- const review = fields.kind === "review";
263948
- if (review && !fields.sponsor)
263949
- out.push({
263950
- field: "sponsor",
263951
- question: `Which marketplace verifies the pros? ${ctx.marketplaces ? `On asks.world today: ${ctx.marketplaces}.` : "list_marketplaces names them."} The pros you invite come from its roster, and it earns the marketplace's share of each approved report. Ask the person, even when there is one.`,
263952
- example: '"ixo"'
263953
- });
263954
- if (!fields.title) out.push({ field: "title", question: review ? "What is being reviewed, as one sentence a pro reads first?" : "What is the call, in one sentence?", example: review ? "Try Qi Portal 2.3 as a first-time project owner and tell us where it fails" : "How should a city pay strangers to fix what they find?" });
263955
- if (review && !fields.subject) out.push({ field: "subject", question: "What is reviewed: its name, the version to test, and where a pro finds it (a public address). Put test accounts and anything private in the invitation, not here: the pro ask is readable by everyone on its list.", example: '{ "name": "Qi Portal", "version": "2.3.0", "where": "https://staging.qi.space" }' });
263956
- if (review && !fields.scenarios?.length) out.push({ field: "scenarios", question: "The scenarios to try, one line each, up to eight: the tasks a real user comes to do. Every report must cover each with a step.", example: '["Sign up with the invite link on a phone that has never seen the app", "Create a project and add two members", "Export the project and open it on a laptop"]' });
263957
- if (!fields.mode && !review)
263958
- out.push({
263959
- field: "mode",
263960
- question: "A competition, or a hire? A competition has a pick and runners-up beside the paid entries. A hire pays every entry that passes the lines the same, up to a number, and picks nobody: hiring five pros at 20 each is a hire.",
263961
- example: '"hire"'
263962
- });
263963
- if (!fields.lede) out.push({ field: "lede", question: "Two or three sentences under the title: what you want and why.", example: "We want one page on a rule a city could actually run. The pick runs on the network for a month." });
263964
- if (!fields.brief?.length)
263965
- out.push({ field: "brief", question: "The story, up to eight short paragraphs: what you are asking for, what good looks like, what happens to the pick.", example: '["What we are asking for\u2026", "What good looks like\u2026", "What happens to the pick\u2026"]' });
263966
- if (linesOf(fields)?.length !== L2.lines)
263967
- out.push({
263968
- field: "lines",
263969
- question: 'The five requirements the jury reviews. Each is a must a good entry passes ("text"), and what fails it ("fail"), written as the end of the sentence "Fail this only if \u2026" \u2014 a clause, not a sentence of its own. An entry must pass all five to be paid.',
263970
- example: '[{ "text": "It puts a price on one fix", "fail": "there is no number" }, \u2026five in all]'
263971
- });
263972
- if (!fields.money)
263973
- out.push(
263974
- review ? {
263975
- field: "money",
263976
- question: `What each pro receives for a report that passes the lines, and how many reports you will pay for (one per pro). In dollars.${ctx.holds ? ` You hold ${ctx.holds}.` : ""}`,
263977
- example: '{ "entry_each": 120, "entry_up_to": 3 }'
263978
- } : fields.mode === "hire" ? {
263979
- field: "money",
263980
- question: `What each entry that passes earns, and up to how many entries you will pay for. In dollars.${ctx.holds ? ` You hold ${ctx.holds}.` : ""}`,
263981
- example: '{ "entry_each": 20, "entry_up_to": 5 }'
263982
- } : {
263983
- field: "money",
263984
- question: `The prize for the pick; runners-up, how many and what each gets; what every entry that passes earns, and up to how many. In dollars.${ctx.holds ? ` You hold ${ctx.holds}.` : ""}`,
263985
- example: '{ "prize": 2, "runners_n": 2, "runners_each": 0.5, "entry_each": 0.2, "entry_up_to": 5 }'
263986
- }
263987
- );
263988
- if (!fields.openDays)
263989
- out.push(
263990
- fields.mode === "hire" ? { field: "open_days", question: "How many days the call takes entries, 1 to 30. Every passing entry is paid as it is judged; nothing waits for a pick.", example: "7" } : { field: "open_days", question: "How many days the call stays open, 1 to 30. The shortlist shows the day after it closes; you pick three days later.", example: "7" }
263991
- );
263992
- if (!review && !fields.access)
263993
- out.push({
263994
- field: "access",
263995
- question: `Who may enter? "public": anyone, listed on the board. "apply": listed, but people apply and you say yes to each before they can enter. "invite": not listed; only people you invite, by address, by their page's @handle, or with a link that admits one new person each.`,
263996
- example: '"invite"'
263997
- });
263998
- if (!review && fields.access === "invite" && !fields.invite?.length)
263999
- out.push({ field: "invite", question: 'Who to invite: ixo1 addresses, @handles of people with a page, and "link" once per single-use link to mint. You can add more later with invite_to_call. Access details they need (a staging address, a test account) go in invite_note, which only the people invited read.', example: '["link", "link", "@ana"]' });
264000
- if (!fields.start && !review)
264001
- out.push({
264002
- field: "start",
264003
- question: "The first message an entrant should paste into their AI. Offer this one unless they want their own.",
264004
- example: `Read the open call "${fields.title ?? "\u2026"}" on asks.world with read_ask, then help me write one page in my own words that addresses all five requirements. Ask me what I know first; file it with submit_work only when I say so.`
264005
- });
264006
- return out;
264007
- }
264008
- function optionalOf(fields, site) {
264009
- const samples = `${site}/opencall/samples`;
264010
- const out = [];
264011
- if (!fields.cover) out.push(`cover: { url, alt, caption? } \u2014 a picture that heads the call. None yet; a drawn sample: ${samples}/cover.svg`);
264012
- if (!fields.pictures?.length) out.push(`pictures: up to 6 of { url, alt, caption? } \u2014 what good looks like. Drawn samples: ${samples}/lamp.svg, ${samples}/lane.svg, ${samples}/drain.svg`);
264013
- if (!fields.diagram) out.push("diagram: { title, source } \u2014 a mermaid flowchart; its A --> B lines become numbered steps");
264014
- if (!fields.data) out.push("data: { title, csv, note? } \u2014 up to 4,000 characters of CSV; the first number column is drawn as bars");
264015
- if (!fields.files?.length) out.push("files: up to 6 of { url, name, note? } \u2014 what to read first");
264016
- if (!fields.poster) out.push("poster: how you want to be named on the call (default: the account it posts as)");
264017
- return out;
264018
- }
264019
- function blocksOf(fields) {
264020
- const blocks = [];
264021
- if (fields.cover) blocks.push({ kind: "cover", ...fields.cover });
264022
- if (fields.brief?.length) blocks.push({ kind: "story", paragraphs: fields.brief });
264023
- if (fields.pictures?.length) blocks.push({ kind: "pictures", items: fields.pictures });
264024
- if (fields.diagram) blocks.push({ kind: "diagram", title: fields.diagram.title, steps: stepsFromMermaid(fields.diagram.source), source: fields.diagram.source });
264025
- if (fields.data) blocks.push({ kind: "data", ...fields.data });
264026
- if (fields.files?.length) blocks.push({ kind: "files", items: fields.files });
264027
- if (fields.start) blocks.push({ kind: "start", prompt: fields.start });
264028
- else if (fields.kind === "review") blocks.push({ kind: "start", prompt: reviewStart(fields.title) });
264029
- return blocks;
264030
- }
264031
- function callOfDraft(draft, poster, dates, legs, share, sponsor) {
264032
- const f = draft.fields;
264033
- if (!isReady(f) || !f.money) throw new Error("the draft is not ready to post");
264034
- return {
264035
- slug: draft.slug,
264036
- ...f.mode === "hire" ? { mode: "hire" } : {},
264037
- ...f.kind === "review" ? { kind: "review", ...f.subject ? { subject: f.subject } : {}, ...f.scenarios?.length ? { scenarios: f.scenarios } : {} } : {},
264038
- title: f.title,
264039
- lede: f.lede,
264040
- poster: f.poster ?? poster,
264041
- points: linesOf(f).map(() => 100 / L2.lines),
264042
- money: f.mode === "hire" ? { ...f.money, prize: 0, runnersN: 0, runnersEach: 0 } : f.money,
264043
- ...share ? { share: { network: share.network, node: share.node } } : {},
264044
- ...sponsor ? { sponsor: { slug: sponsor.slug, name: sponsor.name, node: sponsor.node } } : {},
264045
- ...dates,
264046
- ...legs && Object.keys(legs).length ? { legs } : {},
264047
- blocks: blocksOf(f)
264048
- };
264049
- }
264050
- function legPlan(fields, leg, checkBase, share, feeInReward = false) {
264051
- const m = fields.money;
264052
- const priced = (payBase) => {
264053
- const legBase = share ? grossFor(payBase, share) : payBase;
264054
- return { payBase, legBase, shareBase: legBase - payBase };
264055
- };
264056
- if (leg === "entries") {
264057
- const pay2 = priced(toBase2(m.entryEach));
264058
- if (feeInReward) return { leg, ...pay2, quota: m.entryUpTo, escrowSpots: m.entryUpTo, checkBase, escrowBase: (pay2.legBase + checkBase) * m.entryUpTo, feeBase: 0 };
264059
- return { leg, ...pay2, quota: m.entryUpTo, escrowSpots: m.entryUpTo, checkBase, escrowBase: pay2.legBase * m.entryUpTo, feeBase: checkBase * m.entryUpTo };
264060
- }
264061
- const winners = leg === "prize" ? 1 : m.runnersN;
264062
- const pay = priced(toBase2(leg === "prize" ? m.prize : m.runnersEach));
264063
- return { leg, ...pay, quota: pickQuota(winners), escrowSpots: winners, checkBase: 0, escrowBase: pay.legBase * winners, feeBase: 0 };
264064
- }
264065
- function callShare(fields, split3) {
264066
- if (!callShares(fields)) return { share: null };
264067
- return split3 ? { share: { network: split3.network, node: split3.node } } : { unread: true };
264068
- }
264069
- function legTerms(draft, leg, ctx) {
264070
- const access2 = accessOf(draft.fields);
264071
- if (leg === "entries") {
264072
- const legs = { ...draft.posted.prize ? { prize: draft.posted.prize.id } : {}, ...draft.posted.runnersUp ? { runnersUp: draft.posted.runnersUp.id } : {} };
264073
- const review = draft.fields.kind === "review";
264074
- return {
264075
- ...callEntriesTerms({
264076
- call: callOfDraft(draft, ctx.poster, ctx.dates, legs, ctx.share, ctx.sponsor),
264077
- lines: linesOf(draft.fields),
264078
- judge: ctx.oracle,
264079
- access: access2,
264080
- ...review ? { report: draft.fields.report ?? [] } : {},
264081
- ...review && ctx.approver ? { approver: ctx.approver } : {}
264082
- }),
264083
- via: "mcp"
264084
- };
264085
- }
264086
- return { ...callPickTerms({ call: callOfDraft(draft, ctx.poster, ctx.dates, void 0, ctx.share, ctx.sponsor), leg, access: access2 }), via: "mcp" };
264087
- }
264088
- function callPlan(draft, ctx, now3 = Date.now()) {
264089
- if (callShares(draft.fields) !== Boolean(ctx.share)) throw new Error(ctx.share ? "only a private call carries the network's share" : "a private call is priced with the network's share: read the split first (callShare)");
264090
- const dates = draft.dates ?? callDates(draft.fields.openDays, now3, draft.fields.mode === "hire" ? "hire" : void 0);
264091
- const entries2 = legTerms(draft, "entries", { poster: ctx.poster, dates, oracle: { kind: "oracle", address: ctx.oracle }, share: ctx.share, sponsor: ctx.sponsor });
264092
- const checkBase = ctx.checkerLegBase(entries2);
264093
- const legs = legOrder(draft.fields).map((leg) => legPlan(draft.fields, leg, checkBase, ctx.share, ctx.feeInReward));
264094
- return { legs, totalBase: legs.reduce((sum, one) => sum + one.escrowBase, 0), dates, share: ctx.share };
264095
- }
264096
264127
  function capWords(legs, capBase, symbol2, network2) {
264097
264128
  const at = (base6) => payWords(base6, symbol2, network2);
264098
264129
  const fitting = (base6) => Math.floor(base6 / 1e4) * 1e4;
@@ -264384,9 +264415,9 @@ function confirms(said3, totalBase, symbol2) {
264384
264415
  const named = /USDC|PAY|IXO/i.exec(said3)?.[0]?.toUpperCase();
264385
264416
  if (symbol2 && named && named !== symbol2.toUpperCase()) return false;
264386
264417
  const figure = said3.replace(/[$,\s]|USDC|PAY|IXO/gi, "");
264387
- return /^\d+(\.\d+)?$/.test(figure) && Math.round(Number(figure) * MICRO4) === totalBase;
264418
+ return /^\d+(\.\d+)?$/.test(figure) && Math.round(Number(figure) * MICRO5) === totalBase;
264388
264419
  }
264389
- var MICRO4, callsDir, fileOf, askInvitesFile, freshDraft, L2, ENTRIES_MAX, INVITES_MAX, INVITE_NOTE_MAX, ADDRESS2, HANDLE_ITEM, isInviteItem, PRO_ASK_INVITE_ONLY, PRO_ASK_NEEDS_MARKETPLACE, manyLines, linesOf, nudgeAtFor, reviewStart, isReady, legOrder, accessOf, nextLeg, toBase2, callShares, SHARE_UNREAD, overCap, callTwoCoins, SETTLE_MS, chainCheck, InFlightError, PostRefused, said2, indexLookupWith, indexLookup, posting, isAskPending, isTxFailed, tagOf, TESTNET_CALL_DEFAULTS, payWords;
264420
+ var MICRO5, callsDir, fileOf, askInvitesFile, freshDraft, L3, ENTRIES_MAX, INVITES_MAX, INVITE_NOTE_MAX, ADDRESS2, HANDLE_ITEM, isInviteItem, PRO_ASK_INVITE_ONLY, PRO_ASK_NEEDS_MARKETPLACE, manyLines, overCap, callTwoCoins, SETTLE_MS, chainCheck, InFlightError, PostRefused, said2, indexLookupWith, indexLookup, posting, isAskPending, isTxFailed, tagOf, TESTNET_CALL_DEFAULTS, payWords;
264390
264421
  var init_call2 = __esm({
264391
264422
  "src/call.ts"() {
264392
264423
  "use strict";
@@ -264399,8 +264430,10 @@ var init_call2 = __esm({
264399
264430
  init_dollars();
264400
264431
  init_networks();
264401
264432
  init_checkers();
264433
+ init_callTerms();
264434
+ init_callTerms();
264402
264435
  init_callRead();
264403
- MICRO4 = 1e6;
264436
+ MICRO5 = 1e6;
264404
264437
  callsDir = () => join6(process.env.OPENHANDS_HOME || join6(homedir3(), ".openhands"), currentNetwork2(), "calls");
264405
264438
  fileOf = (slug) => join6(callsDir(), `${slug}.json`);
264406
264439
  askInvitesFile = (askId) => join6(callsDir(), "..", "asks", `${askId.replace(/\D/g, "")}.json`);
@@ -264413,7 +264446,7 @@ var init_call2 = __esm({
264413
264446
  dates: null,
264414
264447
  posted: { prize: null, runnersUp: null, entries: null }
264415
264448
  });
264416
- L2 = CALL_LIMITS;
264449
+ L3 = CALL_LIMITS;
264417
264450
  ENTRIES_MAX = 50;
264418
264451
  INVITES_MAX = 50;
264419
264452
  INVITE_NOTE_MAX = 300;
@@ -264423,22 +264456,6 @@ var init_call2 = __esm({
264423
264456
  PRO_ASK_INVITE_ONLY = `A pro ask is by invitation only (access "invite"): its pros come from its marketplace's roster`;
264424
264457
  PRO_ASK_NEEDS_MARKETPLACE = "A pro ask names its marketplace: call draft_call with sponsor.";
264425
264458
  manyLines = (value) => value.replace(/\r\n?/g, "\n").replace(/\t/g, ",").trim();
264426
- linesOf = (fields) => fields.lines ?? (fields.kind === "review" ? [...REVIEW_LINES] : void 0);
264427
- nudgeAtFor = (network2, judge) => {
264428
- const asky = askyChecker(network2);
264429
- return asky && judge === asky.address ? { url: asky.url } : null;
264430
- };
264431
- reviewStart = (title) => (
264432
- /* The person copies this into their agent, so it is in their words: no tool names (expert prompts review, 2.6). */
264433
- `I'm taking part in the review "${title ?? "\u2026"}" on pro.asks.world. Show me what the review asks for, then help me try each scenario and keep notes and screenshots as I go: what I did, what I expected and what I saw. Write up my findings with me, each with how serious it is and how to reproduce it, and my recommendations. Show me all of it, and hand it in as my report only when I say so.`
264434
- );
264435
- isReady = (fields) => missingOf(fields, { symbol: "", holds: null }).length === 0;
264436
- legOrder = (fields) => legsOf({ mode: fields.mode === "hire" ? "hire" : void 0, money: fields.money ?? { prize: 0, runnersN: 0, runnersEach: 0, entryEach: 0, entryUpTo: 0 } });
264437
- accessOf = (fields) => fields.access === "apply" || fields.access === "invite" ? fields.access : void 0;
264438
- nextLeg = (draft) => legOrder(draft.fields).find((leg) => !draft.posted[leg]) ?? null;
264439
- toBase2 = (display) => Math.round(display * MICRO4);
264440
- callShares = (fields) => sharedCall({ access: accessOf(fields), call: { kind: fields.kind } });
264441
- SHARE_UNREAD = "Refused: this call is a hire by invitation or application, which carries the network's share, and the fee split could not be read just now, so its leg cannot be priced. Nothing was posted. Try again in a minute.";
264442
264459
  overCap = (leg, capBase) => leg.escrowBase > capBase;
264443
264460
  callTwoCoins = "this call's reviews are held in review credit beside its rewards, and the connection's allowance covers the rewards only. Use a verifier that bills per check (Pay for reviews)";
264444
264461
  SETTLE_MS = 10 * 60 * 1e3;
@@ -264845,31 +264862,31 @@ function readHandProfile(raw) {
264845
264862
  if (!AVAILABILITY.includes(availability)) return { problem: `availability is ${AVAILABILITY.join(", ")}` };
264846
264863
  const invitable = it2.invitable === void 0 ? true : it2.invitable;
264847
264864
  if (typeof invitable !== "boolean") return { problem: "invitable is true or false" };
264848
- const L4 = HAND_LIMITS;
264865
+ const L5 = HAND_LIMITS;
264849
264866
  const pictureUrl = (value, what) => value === void 0 || value === null || value === "" ? void 0 : https3(value) ? value : { problem: `${what} is an https address` };
264850
264867
  const avatar = pictureUrl(it2.avatar, "avatar");
264851
264868
  if (avatar && typeof avatar === "object") return avatar;
264852
264869
  const banner = pictureUrl(it2.banner, "banner");
264853
264870
  if (banner && typeof banner === "object") return banner;
264854
- const location = it2.location === void 0 || it2.location === null || it2.location === "" ? void 0 : oneLine2(it2.location, L4.location);
264855
- if (location === null) return { problem: `location is one line, up to ${L4.location} characters` };
264856
- const timezone = it2.timezone === void 0 || it2.timezone === null || it2.timezone === "" ? void 0 : oneLine2(it2.timezone, L4.timezone);
264871
+ const location = it2.location === void 0 || it2.location === null || it2.location === "" ? void 0 : oneLine2(it2.location, L5.location);
264872
+ if (location === null) return { problem: `location is one line, up to ${L5.location} characters` };
264873
+ const timezone = it2.timezone === void 0 || it2.timezone === null || it2.timezone === "" ? void 0 : oneLine2(it2.timezone, L5.timezone);
264857
264874
  if (timezone === null || timezone && !/^[A-Za-z_+\-\/0-9: ]{1,64}$/.test(timezone)) return { problem: "timezone is an IANA name, e.g. Europe/Ljubljana, or UTC+2" };
264858
264875
  const when3 = (value) => typeof value === "string" && /^\d{4}(-(0[1-9]|1[0-2]))?$/.test(value);
264859
264876
  const experience = [];
264860
264877
  if (it2.experience !== void 0 && it2.experience !== null) {
264861
- if (!Array.isArray(it2.experience) || it2.experience.length > L4.experience) return { problem: `experience is up to ${L4.experience} rows` };
264878
+ if (!Array.isArray(it2.experience) || it2.experience.length > L5.experience) return { problem: `experience is up to ${L5.experience} rows` };
264862
264879
  for (const [at, raw2] of it2.experience.entries()) {
264863
- const title = oneLine2(raw2?.title, L4.title);
264864
- const org = oneLine2(raw2?.org, L4.org);
264880
+ const title = oneLine2(raw2?.title, L5.title);
264881
+ const org = oneLine2(raw2?.org, L5.org);
264865
264882
  if (!title || !org) return { problem: `experience row ${at + 1} needs a title and an org` };
264866
264883
  if (!when3(raw2?.from)) return { problem: `experience row ${at + 1}: from is "YYYY" or "YYYY-MM"` };
264867
264884
  if (!(raw2?.to === null || raw2?.to === void 0 || raw2?.to === "" || when3(raw2?.to))) return { problem: `experience row ${at + 1}: to is "YYYY", "YYYY-MM", or null for now` };
264868
- const where2 = raw2?.where === void 0 || raw2?.where === null || raw2?.where === "" ? void 0 : oneLine2(raw2.where, L4.where);
264885
+ const where2 = raw2?.where === void 0 || raw2?.where === null || raw2?.where === "" ? void 0 : oneLine2(raw2.where, L5.where);
264869
264886
  if (where2 === null) return { problem: `experience row ${at + 1}: where is one line` };
264870
264887
  let what;
264871
264888
  if (raw2?.what !== void 0 && raw2?.what !== null && raw2?.what !== "") {
264872
- if (typeof raw2.what !== "string" || raw2.what.length > L4.what) return { problem: `experience row ${at + 1}: what is up to ${L4.what} characters` };
264889
+ if (typeof raw2.what !== "string" || raw2.what.length > L5.what) return { problem: `experience row ${at + 1}: what is up to ${L5.what} characters` };
264873
264890
  what = raw2.what.replace(/\s+/g, " ").trim();
264874
264891
  }
264875
264892
  experience.push({ title, org, from: raw2.from, to: when3(raw2?.to) ? raw2.to : null, ...where2 ? { where: where2 } : {}, ...what ? { what } : {} });
@@ -264886,16 +264903,16 @@ function readHandProfile(raw) {
264886
264903
  }
264887
264904
  return [...new Set(out)];
264888
264905
  };
264889
- const skills = words5(it2.skills, L4.skills, L4.skill, "skills");
264906
+ const skills = words5(it2.skills, L5.skills, L5.skill, "skills");
264890
264907
  if (!Array.isArray(skills)) return skills;
264891
- const languages = words5(it2.languages, L4.languages, L4.language, "languages");
264908
+ const languages = words5(it2.languages, L5.languages, L5.language, "languages");
264892
264909
  if (!Array.isArray(languages)) return languages;
264893
264910
  const education = [];
264894
264911
  if (it2.education !== void 0 && it2.education !== null) {
264895
- if (!Array.isArray(it2.education) || it2.education.length > L4.education) return { problem: `education is up to ${L4.education} rows` };
264912
+ if (!Array.isArray(it2.education) || it2.education.length > L5.education) return { problem: `education is up to ${L5.education} rows` };
264896
264913
  for (const [at, raw2] of it2.education.entries()) {
264897
- const title = oneLine2(raw2?.title, L4.title);
264898
- const org = oneLine2(raw2?.org, L4.org);
264914
+ const title = oneLine2(raw2?.title, L5.title);
264915
+ const org = oneLine2(raw2?.org, L5.org);
264899
264916
  if (!title || !org) return { problem: `education row ${at + 1} needs a title and an org` };
264900
264917
  if (!(raw2?.year === void 0 || raw2?.year === null || raw2?.year === "" || typeof raw2?.year === "string" && /^\d{4}$/.test(raw2.year))) return { problem: `education row ${at + 1}: year is "YYYY"` };
264901
264918
  education.push({ title, org, ...typeof raw2?.year === "string" && raw2.year ? { year: raw2.year } : {} });
@@ -264903,7 +264920,7 @@ function readHandProfile(raw) {
264903
264920
  }
264904
264921
  const blocks = [];
264905
264922
  if (it2.blocks !== void 0 && it2.blocks !== null) {
264906
- if (!Array.isArray(it2.blocks) || it2.blocks.length > L4.blocks) return { problem: `blocks is up to ${L4.blocks}` };
264923
+ if (!Array.isArray(it2.blocks) || it2.blocks.length > L5.blocks) return { problem: `blocks is up to ${L5.blocks}` };
264907
264924
  for (const [at, raw2] of it2.blocks.entries()) {
264908
264925
  const block2 = readHandBlock(raw2);
264909
264926
  if ("problem" in block2) return { problem: `block ${at + 1}: ${block2.problem}` };
@@ -264938,39 +264955,39 @@ function readHandProfile(raw) {
264938
264955
  function readHandBlock(raw) {
264939
264956
  const it2 = raw;
264940
264957
  if (!it2 || typeof it2 !== "object") return { problem: "a block is an object" };
264941
- const L4 = HAND_LIMITS;
264958
+ const L5 = HAND_LIMITS;
264942
264959
  switch (it2.kind) {
264943
264960
  case "story": {
264944
- if (!Array.isArray(it2.paragraphs) || it2.paragraphs.length === 0 || it2.paragraphs.length > L4.paragraphs) return { problem: `a story is 1 to ${L4.paragraphs} paragraphs` };
264961
+ if (!Array.isArray(it2.paragraphs) || it2.paragraphs.length === 0 || it2.paragraphs.length > L5.paragraphs) return { problem: `a story is 1 to ${L5.paragraphs} paragraphs` };
264945
264962
  const paragraphs = [];
264946
264963
  for (const one of it2.paragraphs) {
264947
- const line2 = oneLine2(one, L4.paragraph);
264948
- if (!line2) return { problem: `a paragraph is one line, up to ${L4.paragraph} characters` };
264964
+ const line2 = oneLine2(one, L5.paragraph);
264965
+ if (!line2) return { problem: `a paragraph is one line, up to ${L5.paragraph} characters` };
264949
264966
  paragraphs.push(line2);
264950
264967
  }
264951
264968
  return { block: { kind: "story", paragraphs } };
264952
264969
  }
264953
264970
  case "pictures": {
264954
- if (!Array.isArray(it2.items) || it2.items.length === 0 || it2.items.length > L4.items) return { problem: `pictures are 1 to ${L4.items}` };
264971
+ if (!Array.isArray(it2.items) || it2.items.length === 0 || it2.items.length > L5.items) return { problem: `pictures are 1 to ${L5.items}` };
264955
264972
  const items = [];
264956
264973
  for (const one of it2.items) {
264957
264974
  if (!https3(one?.url)) return { problem: "a picture's url is an https address" };
264958
- const alt = oneLine2(one?.alt, L4.alt);
264975
+ const alt = oneLine2(one?.alt, L5.alt);
264959
264976
  if (!alt) return { problem: "a picture needs words (alt)" };
264960
- const caption = one?.caption === void 0 || one?.caption === null || one?.caption === "" ? void 0 : oneLine2(one.caption, L4.caption);
264977
+ const caption = one?.caption === void 0 || one?.caption === null || one?.caption === "" ? void 0 : oneLine2(one.caption, L5.caption);
264961
264978
  if (caption === null) return { problem: "a caption is one line" };
264962
264979
  items.push({ url: one.url, alt, ...caption ? { caption } : {} });
264963
264980
  }
264964
264981
  return { block: { kind: "pictures", items } };
264965
264982
  }
264966
264983
  case "files": {
264967
- if (!Array.isArray(it2.items) || it2.items.length === 0 || it2.items.length > L4.items) return { problem: `files are 1 to ${L4.items}` };
264984
+ if (!Array.isArray(it2.items) || it2.items.length === 0 || it2.items.length > L5.items) return { problem: `files are 1 to ${L5.items}` };
264968
264985
  const items = [];
264969
264986
  for (const one of it2.items) {
264970
264987
  if (!https3(one?.url)) return { problem: "a file's url is an https address" };
264971
- const name8 = oneLine2(one?.name, L4.fileName);
264988
+ const name8 = oneLine2(one?.name, L5.fileName);
264972
264989
  if (!name8) return { problem: "a file needs a name" };
264973
- const note = one?.note === void 0 || one?.note === null || one?.note === "" ? void 0 : oneLine2(one.note, L4.note);
264990
+ const note = one?.note === void 0 || one?.note === null || one?.note === "" ? void 0 : oneLine2(one.note, L5.note);
264974
264991
  if (note === null) return { problem: "a file's note is one line" };
264975
264992
  items.push({ url: one.url, name: name8, ...note ? { note } : {} });
264976
264993
  }
@@ -265866,8 +265883,8 @@ function defaultReviewer(oracles, fallback, off) {
265866
265883
  return oracles.find((oracle) => ASK_THE_WORLD_CHECKERS2.has(oracle.address) && !oracle.unavailable && !off?.has(oracle.address)) ?? fallback;
265867
265884
  }
265868
265885
  function goodFor(address2, named) {
265869
- if (ASK_THE_WORLD_CHECKERS2.has(address2)) return "Good for photos, a quick look somewhere and short written answers. The default for an ordinary ask";
265870
- if (named) return "Good for cleanups, before-and-after photos and site work. The default for those";
265886
+ if (ASK_THE_WORLD_CHECKERS2.has(address2)) return "Good for photos, a quick look somewhere and short written answers";
265887
+ if (named) return "Good for cleanups, photos and written answers. The default for every new ask";
265871
265888
  return null;
265872
265889
  }
265873
265890
  var ASK_THE_WORLD_CHECKERS2, NETWORK_CHECKER_ROLE, plainReviewerName, isWorkAsk;
@@ -265875,7 +265892,7 @@ var init_reviewerPick = __esm({
265875
265892
  "../../app/lib/reviewerPick.ts"() {
265876
265893
  "use strict";
265877
265894
  ASK_THE_WORLD_CHECKERS2 = /* @__PURE__ */ new Set(["ixo1qrk9dp4r2u8q5l9cs42yh4dne4pj3wynp4enwq", "ixo12mvzayzrzsvaud86jf9shy6q2nvkea3tygxhsh"]);
265878
- NETWORK_CHECKER_ROLE = "The default verifier for cleanups and site work. An ordinary ask defaults to the Ask the World verifier where this network carries it";
265895
+ NETWORK_CHECKER_ROLE = "The default verifier for every new ask";
265879
265896
  plainReviewerName = (name8) => name8.replace(/\boracle\b/gi, (word) => word[0] === "O" ? "Verifier" : "verifier");
265880
265897
  isWorkAsk = (terms) => terms.deliverable.type === "photo-pair" || terms.deliverable.type === "mess-report" || Boolean(terms.site || terms.campaign);
265881
265898
  }
@@ -266548,6 +266565,8 @@ __export(takeBack_exports, {
266548
266565
  answerArrived: () => answerArrived,
266549
266566
  putBack: () => putBack,
266550
266567
  putBackMsgs: () => putBackMsgs,
266568
+ raiseQuota: () => raiseQuota2,
266569
+ raiseQuotaMsgs: () => raiseQuotaMsgs2,
266551
266570
  readTakeBack: () => readTakeBack,
266552
266571
  takeBack: () => takeBack,
266553
266572
  takeBackMsgs: () => takeBackMsgs,
@@ -266624,22 +266643,33 @@ function selfGrant(owner, grantee, entityDid, authorization) {
266624
266643
  })
266625
266644
  };
266626
266645
  }
266646
+ function quotaMsgs(args) {
266647
+ return [
266648
+ selfGrant(args.owner, args.grantee, args.entityDid, generic(UPDATE_QUOTA)),
266649
+ exec(
266650
+ args.grantee,
266651
+ UPDATE_QUOTA,
266652
+ ixo.claims.v1beta1.MsgUpdateCollectionQuota.encode(
266653
+ ixo.claims.v1beta1.MsgUpdateCollectionQuota.fromPartial({ collectionId: args.collectionId, quota: long_default.fromNumber(args.quota), adminAddress: args.admin })
266654
+ ).finish()
266655
+ )
266656
+ ];
266657
+ }
266658
+ function raiseQuotaMsgs2(args) {
266659
+ if (!(args.quota > 0) || !Number.isInteger(args.more) || args.more < 1) throw new Error("This ask has no spot count to raise");
266660
+ return quotaMsgs({ ...args, grantee: args.owner, quota: args.quota + args.more });
266661
+ }
266662
+ async function raiseQuota2(session, args, prompt, rest = restUrl()) {
266663
+ const collection = await fetch(`${rest}/ixo/claims/collection/${encodeURIComponent(args.collectionId)}`, { signal: AbortSignal.timeout(15e3) }).then((response) => response.ok ? response.json() : null).then((body) => body?.collection ?? null);
266664
+ if (!collection?.admin) throw new Error("The chain didn't return this ask. Try again in a moment");
266665
+ const messages = raiseQuotaMsgs2({ owner: session.address, entityDid: args.entityDid, collectionId: args.collectionId, admin: collection.admin, quota: Number(num4(collection.quota)), more: args.more });
266666
+ return signWithSession(session, messages, `Add ${args.more} ${args.more === 1 ? "answer" : "answers"} to the ask`, prompt);
266667
+ }
266627
266668
  function takeBackMsgs(args) {
266628
266669
  const { owner, entityDid, collectionId, plan } = args;
266629
266670
  const grantee = args.grantee ?? owner;
266630
266671
  const messages = [];
266631
- if (plan.pinQuota !== null) {
266632
- messages.push(
266633
- selfGrant(owner, grantee, entityDid, generic(UPDATE_QUOTA)),
266634
- exec(
266635
- grantee,
266636
- UPDATE_QUOTA,
266637
- ixo.claims.v1beta1.MsgUpdateCollectionQuota.encode(
266638
- ixo.claims.v1beta1.MsgUpdateCollectionQuota.fromPartial({ collectionId, quota: long_default.fromNumber(plan.pinQuota), adminAddress: plan.admin })
266639
- ).finish()
266640
- )
266641
- );
266642
- }
266672
+ if (plan.pinQuota !== null) messages.push(...quotaMsgs({ owner, grantee, entityDid, collectionId, admin: plan.admin, quota: plan.pinQuota }));
266643
266673
  if (plan.close) {
266644
266674
  messages.push(
266645
266675
  selfGrant(owner, grantee, entityDid, generic(UPDATE_STATE)),
@@ -267002,10 +267032,10 @@ function checkSponsorPage(page) {
267002
267032
  if (!record2(page)) return "A page is its deck line, logo, cover, story, steps, pictures and links";
267003
267033
  const stray = Object.keys(page).find((key) => !PAGE_FIELDS.has(key));
267004
267034
  if (stray) return `A page has no "${stray.slice(0, 40)}"; it carries a deck line, logo, cover, story, steps, pictures and links`;
267005
- return maybeWords(page.deck, SPONSOR_PAGE_LIMITS.deck, "The deck line") ?? (page.logo === void 0 ? null : typeof page.logo === "string" && isHttps2(page.logo) ? null : `The logo: "${String(page.logo).slice(0, 80)}" is not an https address`) ?? (page.cover === void 0 ? null : pictureOf(page.cover, "The cover")) ?? many(page.story, L3.paragraphs, "paragraphs", (one, index) => typeof one === "string" ? within(one, L3.paragraph, `Paragraph ${index + 1}`, true) : `Paragraph ${index + 1} is not words`) ?? many(page.steps, L3.steps, "steps", (one, index) => record2(one) ? words4(one.title, L3.stepTitle, `Step ${index + 1}'s title`) ?? maybeWords(one.text, L3.stepText, `Step ${index + 1}'s words`) : `Step ${index + 1} needs a title`) ?? many(page.pictures, L3.items, "pictures", (one, index) => pictureOf(one, `Picture ${index + 1}`)) ?? many(page.links, SPONSOR_PAGE_LIMITS.links, "links", (one, index) => {
267035
+ return maybeWords(page.deck, SPONSOR_PAGE_LIMITS.deck, "The deck line") ?? (page.logo === void 0 ? null : typeof page.logo === "string" && isHttps2(page.logo) ? null : `The logo: "${String(page.logo).slice(0, 80)}" is not an https address`) ?? (page.cover === void 0 ? null : pictureOf(page.cover, "The cover")) ?? many(page.story, L4.paragraphs, "paragraphs", (one, index) => typeof one === "string" ? within(one, L4.paragraph, `Paragraph ${index + 1}`, true) : `Paragraph ${index + 1} is not words`) ?? many(page.steps, L4.steps, "steps", (one, index) => record2(one) ? words4(one.title, L4.stepTitle, `Step ${index + 1}'s title`) ?? maybeWords(one.text, L4.stepText, `Step ${index + 1}'s words`) : `Step ${index + 1} needs a title`) ?? many(page.pictures, L4.items, "pictures", (one, index) => pictureOf(one, `Picture ${index + 1}`)) ?? many(page.links, SPONSOR_PAGE_LIMITS.links, "links", (one, index) => {
267006
267036
  if (!record2(one) || typeof one.url !== "string") return `Link ${index + 1} needs an address and a name`;
267007
267037
  if (!isHttps2(one.url)) return `Link ${index + 1}: "${one.url.slice(0, 80)}" is not an https address`;
267008
- return words4(one.name, L3.name, `Link ${index + 1}'s name`) ?? maybeWords(one.note, L3.note, `Link ${index + 1}'s note`);
267038
+ return words4(one.name, L4.name, `Link ${index + 1}'s name`) ?? maybeWords(one.note, L4.note, `Link ${index + 1}'s note`);
267009
267039
  });
267010
267040
  }
267011
267041
  function tidySponsorPage(page) {
@@ -267032,7 +267062,7 @@ function sponsorBlocks(page, name8) {
267032
267062
  if (page.links?.length) blocks.push({ kind: "files", items: page.links.map((one) => ({ url: one.url, name: oneLine(one.name), ...one.note ? { note: oneLine(one.note) } : {} })) });
267033
267063
  return blocks;
267034
267064
  }
267035
- var SPONSOR_METHOD_MAX, sponsorBySlug, SPONSOR_SLUG, slugOf, sponsorNode, sponsorAccounts, SPONSOR_PAGE_LIMITS, PAGE_FIELDS, L3, words4, maybeWords, record2, many, pictureOf, tidyPicture;
267065
+ var SPONSOR_METHOD_MAX, sponsorBySlug, SPONSOR_SLUG, slugOf, sponsorNode, sponsorAccounts, SPONSOR_PAGE_LIMITS, PAGE_FIELDS, L4, words4, maybeWords, record2, many, pictureOf, tidyPicture;
267036
267066
  var init_sponsors = __esm({
267037
267067
  "../../packages/openhands-sdk/src/data/sponsors.ts"() {
267038
267068
  "use strict";
@@ -267052,7 +267082,7 @@ var init_sponsors = __esm({
267052
267082
  sponsorAccounts = (list7) => new Set(list7.filter((s) => s.state === "approved").map((s) => s.account));
267053
267083
  SPONSOR_PAGE_LIMITS = { deck: 120, links: 6 };
267054
267084
  PAGE_FIELDS = /* @__PURE__ */ new Set(["deck", "logo", "cover", "story", "steps", "pictures", "links"]);
267055
- L3 = CALL_LIMITS;
267085
+ L4 = CALL_LIMITS;
267056
267086
  words4 = (value, max, what) => typeof value === "string" ? within(oneLine(value), max, what) : `${what} is not words`;
267057
267087
  maybeWords = (value, max, what) => value === void 0 ? null : words4(value, max, what);
267058
267088
  record2 = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
@@ -267468,43 +267498,43 @@ ${where2}`)) {
267468
267498
  askAt = (place) => ` At ${place.name}.`;
267469
267499
  askOverrun = (check2, place) => Math.max(0, askWords(check2).length + askAt(place).length - PLAN_LIMITS.textMax);
267470
267500
  shapeOfCheck = (check2) => {
267471
- const L4 = PLAN_LIMITS;
267501
+ const L5 = PLAN_LIMITS;
267472
267502
  const out = [];
267473
267503
  const bad = (why) => out.push({ rule: "shape", check: check2.id, why });
267474
267504
  if (!PLAN_ACTS.includes(check2.act)) bad(`The act must be one of ${PLAN_ACTS.join(", ")}.`);
267475
267505
  const text4 = check2.text.trim();
267476
- if (text4.length < L4.textMin || text4.length > L4.textMax) bad(`The check's words must be ${L4.textMin}\u2013${L4.textMax} characters.`);
267506
+ if (text4.length < L5.textMin || text4.length > L5.textMax) bad(`The check's words must be ${L5.textMin}\u2013${L5.textMax} characters.`);
267477
267507
  else {
267478
267508
  const named = check2.places.filter((place) => place.name?.trim());
267479
267509
  const worst = named.reduce((most2, place) => !most2 || askOverrun(check2, place) > askOverrun(check2, most2) ? place : most2, null);
267480
267510
  const over = worst ? askOverrun(check2, worst) : 0;
267481
267511
  if (worst && over > 0) {
267482
- bad(`Each ask adds "${askAt(worst).trim()}" after the words, which takes them ${over} characters past the ${L4.textMax} an ask carries. Cut ${over} characters from the words, or shorten that place's name.`);
267512
+ bad(`Each ask adds "${askAt(worst).trim()}" after the words, which takes them ${over} characters past the ${L5.textMax} an ask carries. Cut ${over} characters from the words, or shorten that place's name.`);
267483
267513
  }
267484
267514
  }
267485
267515
  if (!check2.places.length) bad("A check needs at least one place.");
267486
- if (check2.places.length > L4.placesPerCheck) bad(`A check holds at most ${L4.placesPerCheck} places.`);
267516
+ if (check2.places.length > L5.placesPerCheck) bad(`A check holds at most ${L5.placesPerCheck} places.`);
267487
267517
  for (const place of check2.places) {
267488
267518
  if (!place.name?.trim()) bad("Every place needs a name a person recognises.");
267489
267519
  if (!(Math.abs(place.lat) <= 90) || !(Math.abs(place.lon) <= 180) || place.lat === 0 && place.lon === 0) bad(`"${place.name}" has no usable coordinates.`);
267490
- if (!(place.withinM >= L4.withinMin && place.withinM <= L4.withinMax)) bad(`"${place.name}": the distance must be ${L4.withinMin}\u2013${L4.withinMax} m.`);
267520
+ if (!(place.withinM >= L5.withinMin && place.withinM <= L5.withinMax)) bad(`"${place.name}": the distance must be ${L5.withinMin}\u2013${L5.withinMax} m.`);
267491
267521
  }
267492
- const most = check2.act === "survey" ? L4.surveyPerPlace : L4.perPlace;
267522
+ const most = check2.act === "survey" ? L5.surveyPerPlace : L5.perPlace;
267493
267523
  if (!Number.isInteger(check2.perPlace) || check2.perPlace < 1 || check2.perPlace > most) bad(`Answers per place must be a whole number from 1 to ${most}.`);
267494
267524
  if (check2.act === "survey") {
267495
267525
  const problem = surveyOptionsProblem(check2.options);
267496
267526
  if (problem) bad(problem);
267497
267527
  } else if (check2.options !== void 0) bad("Only a survey has options.");
267498
267528
  for (const [name8, line2] of [["why", check2.why], ["how it is read", check2.readAs]]) {
267499
- if (line2 !== void 0 && (line2.trim().length < L4.lineMin || line2.trim().length > L4.lineMax)) bad(`The check's ${name8} line is ${L4.lineMin}\u2013${L4.lineMax} characters.`);
267529
+ if (line2 !== void 0 && (line2.trim().length < L5.lineMin || line2.trim().length > L5.lineMax)) bad(`The check's ${name8} line is ${L5.lineMin}\u2013${L5.lineMax} characters.`);
267500
267530
  }
267501
- if (!(check2.payUsd >= L4.payFloorUsd)) bad(`The pay must be at least $${L4.payFloorUsd.toFixed(2)} an answer.`);
267502
- if (!(check2.hours >= L4.hoursMin && check2.hours <= L4.hoursMax)) bad(`A check stays open ${L4.hoursMin}\u2013${L4.hoursMax} hours.`);
267503
- if (check2.beats.trim().length > L4.lineMax) bad(`What the check beats fits in ${L4.lineMax} characters.`);
267531
+ if (!(check2.payUsd >= L5.payFloorUsd)) bad(`The pay must be at least $${L5.payFloorUsd.toFixed(2)} an answer.`);
267532
+ if (!(check2.hours >= L5.hoursMin && check2.hours <= L5.hoursMax)) bad(`A check stays open ${L5.hoursMin}\u2013${L5.hoursMax} hours.`);
267533
+ if (check2.beats.trim().length > L5.lineMax) bad(`What the check beats fits in ${L5.lineMax} characters.`);
267504
267534
  return out;
267505
267535
  };
267506
267536
  validatePlan = (plan) => {
267507
- const L4 = PLAN_LIMITS;
267537
+ const L5 = PLAN_LIMITS;
267508
267538
  const refusals = [...screenMarket(plan.market)];
267509
267539
  const shape = (why) => refusals.push({ rule: "shape", check: null, why });
267510
267540
  if (plan.kind !== MARKET_PLAN_KIND || plan.v !== 1) shape("This is not a version 1 plan.");
@@ -267512,15 +267542,15 @@ ${where2}`)) {
267512
267542
  if (!/^https?:\/\//.test(plan.market.url)) shape("The market needs its link.");
267513
267543
  if (plan.market.question.trim().length < 8) shape("The market needs its question.");
267514
267544
  if (!plan.checks.length) shape("A plan needs at least one check.");
267515
- if (plan.checks.length > L4.checks) shape(`A plan holds at most ${L4.checks} checks.`);
267516
- if (planAskCount(plan) > L4.asksPerPlan) shape(`A plan posts at most ${L4.asksPerPlan} asks (one per place per check).`);
267545
+ if (plan.checks.length > L5.checks) shape(`A plan holds at most ${L5.checks} checks.`);
267546
+ if (planAskCount(plan) > L5.asksPerPlan) shape(`A plan posts at most ${L5.asksPerPlan} asks (one per place per check).`);
267517
267547
  const ids = /* @__PURE__ */ new Set();
267518
267548
  for (const check2 of plan.checks) {
267519
267549
  if (ids.has(check2.id)) shape(`Two checks share the id ${check2.id}.`);
267520
267550
  ids.add(check2.id);
267521
267551
  }
267522
- if (plan.thesis !== void 0 && (plan.thesis.trim().length < L4.lineMin || plan.thesis.trim().length > L4.thesisMax)) shape(`The thesis is ${L4.lineMin}\u2013${L4.thesisMax} characters.`);
267523
- if (plan.cannotTell.trim().length < L4.lineMin) {
267552
+ if (plan.thesis !== void 0 && (plan.thesis.trim().length < L5.lineMin || plan.thesis.trim().length > L5.thesisMax)) shape(`The thesis is ${L5.lineMin}\u2013${L5.thesisMax} characters.`);
267553
+ if (plan.cannotTell.trim().length < L5.lineMin) {
267524
267554
  refusals.push({ rule: "no-cannot-tell", check: null, why: "Say what this plan cannot tell the trader. A plan without its limit reads as a promise." });
267525
267555
  }
267526
267556
  for (const check2 of plan.checks) refusals.push(...shapeOfCheck(check2), ...screenCheck(check2));
@@ -292106,7 +292136,7 @@ import { randomBytes as randomBytes7 } from "node:crypto";
292106
292136
  // package.json
292107
292137
  var package_default = {
292108
292138
  name: "@ixo/asks-mcp",
292109
- version: "1.6.0",
292139
+ version: "1.8.0",
292110
292140
  description: "The Openhands Network MCP server: read the board, answer asks, post work and get paid on the ixo chain, with a key of its own on your machine.",
292111
292141
  license: "Apache-2.0",
292112
292142
  repository: {
@@ -294245,7 +294275,7 @@ async function build2(options, server2, parts) {
294245
294275
  if (event === "hire")
294246
294276
  void fetch2(`${SITE}/api/board/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ collectionId }), signal: AbortSignal.timeout(5e3) }).catch(() => void 0);
294247
294277
  };
294248
- const MICRO5 = 1e6;
294278
+ const MICRO6 = 1e6;
294249
294279
  let ASK_DENOM = DEPLOYMENT.askDenom;
294250
294280
  let ASK_SYMBOL = symbolOf(ASK_DENOM);
294251
294281
  const FEE_DENOM = checkerFeeDenom(NETWORK2);
@@ -294261,7 +294291,7 @@ async function build2(options, server2, parts) {
294261
294291
  const FUNDER = ownEnv().OPENHANDS_FUNDER?.trim() || void 0;
294262
294292
  const FOLLOW_PAY_MAX = 10;
294263
294293
  const MAX_PER_ASK = CAPS.perAsk;
294264
- const CAP_BASE = Math.round(MAX_PER_ASK * MICRO5);
294294
+ const CAP_BASE = Math.round(MAX_PER_ASK * MICRO6);
294265
294295
  const MAX_PER_DAY = CAPS.perDay;
294266
294296
  const MAX_PER_DAY_TOTAL = CAPS.total;
294267
294297
  const ALL_TOOLS = "all";
@@ -294297,7 +294327,7 @@ async function build2(options, server2, parts) {
294297
294327
  }
294298
294328
  function dayRoom(bucket, amount3, bucketCeiling = MAX_PER_DAY) {
294299
294329
  try {
294300
- const units2 = (value) => Math.round(value * MICRO5);
294330
+ const units2 = (value) => Math.round(value * MICRO6);
294301
294331
  for (const [name8, ceiling] of [
294302
294332
  [bucket, bucketCeiling],
294303
294333
  [ALL_TOOLS, MAX_PER_DAY_TOTAL]
@@ -294934,7 +294964,7 @@ Never open it yourself.`
294934
294964
  "Posting the same job many times, one per address? Give every one the same series name (lowercase letters, digits, dashes) and the board shows them as one card. Each is still its own ask and pays on its own."
294935
294965
  ),
294936
294966
  org: external_exports.string().optional().describe("Post for this organisation: its id (`did:ixo:entity:\u2026`). The ask is a deed the organisation requests (linked both ways); you need a key on the organisation, and to own it when the ask holds money: the organisation's account funds the deed (pay x quota in the network's reward coin, shown as dollars, plus the review fee), never this key's account. Needs the IXO ask shape on this deployment."),
294937
- oracle: external_exports.object({ did: external_exports.string(), address: external_exports.string().optional(), url: external_exports.string().url().optional() }).optional().describe("With org: the verifier that judges the ask. With url, its published price is the evaluation payment, in the network's verifier-fee coin, shown as dollars, paid by the organisation's account, which must hold it; without url (your own verifier) the evaluation payment is 0. address: a `did:ixo:entity` verifier's signing account is read from the public record (its #orz), so leave it out; if given it must match. A `did:web` verifier needs it. Omitted: an ordinary ask (a photo, words, a file) is checked by IXO's Ask the World verifier where this network carries it (for an org, only when its settings allow it, else the org's default); a cleanup, work or campaign ask by the network's own verifier."),
294967
+ oracle: external_exports.object({ did: external_exports.string(), address: external_exports.string().optional(), url: external_exports.string().url().optional() }).optional().describe("With org: the verifier that judges the ask. With url, its published price is the evaluation payment, in the network's verifier-fee coin, shown as dollars, paid by the organisation's account, which must hold it; without url (your own verifier) the evaluation payment is 0. address: a `did:ixo:entity` verifier's signing account is read from the public record (its #orz), so leave it out; if given it must match. A `did:web` verifier needs it. Omitted: the asks.world verifier (this network's own) checks it; for an org, one its settings allow."),
294938
294968
  payout: external_exports.object({ rail: external_exports.enum(["usdc_base", "stripe"]), amount: external_exports.number().positive().max(1e6), currency: external_exports.string(), facilitator: external_exports.string() }).optional().describe("With org: pay the worker through the organisation's payouts service (`did:web` or https URL), not from the ask. pay must be 0."),
294939
294969
  campaign: external_exports.string().optional().describe("Post the ask in this campaign: the campaign's protocol id (`did:ixo:entity:\u2026`, from create_campaign). The deed is classed under it and partOf it, and checked against the campaign's shared requirements. Needs the IXO ask shape."),
294940
294970
  image: external_exports.string().optional().describe("The ask's picture (png, jpg or webp, at most 5 MB): a file path on this machine, an https URL or a data: URL. Stored on the gateway and set as the deed's profile image. Needs the IXO ask shape."),
@@ -295065,11 +295095,7 @@ Never open it yourself.`
295065
295095
  } catch (error54) {
295066
295096
  return text4(`Refused: ${error54 instanceof Error ? error54.message : String(error54)}. Nothing was posted and nothing was spent.`);
295067
295097
  }
295068
- let reviewer = expert ? expert.checker.address : CHECKER;
295069
- if (!orgAsk && ordinary) {
295070
- const priced = await askTheWorldPriced();
295071
- if (priced) ({ address: reviewer, leg: legBase, perCheck } = priced);
295072
- }
295098
+ const reviewer = expert ? expert.checker.address : CHECKER;
295073
295099
  const { payoutSummary: payoutSummary2, railWords: railWords2, payoutTermsJson: payoutTermsJson2, payoutTermsCid: payoutTermsCid2 } = await Promise.resolve().then(() => (init_payoutTerms(), payoutTerms_exports));
295074
295100
  const built = {
295075
295101
  ...form.terms,
@@ -295140,7 +295166,7 @@ ${orgCosts}` } : { total: onChain.total, what: perCheck ? `${onChain.what}. Revi
295140
295166
  /* By card the person posts as themselves at the link; and a hosted server has no connection to name. */
295141
295167
  card ? null : actingNote(acting),
295142
295168
  expert ? expertNote(expert) : checkingNote(terms, acting?.principal ?? null),
295143
- expert ? null : orgAsk ? `Reviewed by ${await oracleWordsFor({ did: orgAsk.oracle.did, address: orgAsk.oracle.address })}.` : reviewer && reviewer !== CHECKER ? `Reviewed by ${await oracleWordsFor({ address: reviewer })}.` : null,
295169
+ expert ? null : orgAsk ? `Reviewed by ${await oracleWordsFor({ did: orgAsk.oracle.did, address: orgAsk.oracle.address })}.` : reviewer && reviewer !== CHECKER ? `Reviewed by ${await oracleWordsFor({ address: reviewer })}.` : reviewer ? `Checked by asks.world verifier, ${feeWords(perCheck ? perCheck.price : legBase)} per check.` : null,
295144
295170
  doorWords(door2.access, door2.invite.length),
295145
295171
  inCampaign ? `In campaign ${inCampaign.protocolDid}, checked by its shared rules (${inCampaign.claimProtocolDid}).` : null,
295146
295172
  picture2 && !("refused" in picture2) ? `Picture: ${picture2.contentType.slice(6)}, ${Math.ceil(picture2.bytes.byteLength / 1024)} KB, uploaded through your account connection with the ask.` : null,
@@ -295242,7 +295268,7 @@ ${SITE}/t/${earlier.id}`);
295242
295268
  }
295243
295269
  const callLocks = (rewardBase, feeBase, symbol2 = ASK_SYMBOL) => `${pays(rewardBase, symbol2)}${feeBase > 0 ? ` and ${feeWords(feeBase)} for reviews` : ""}`;
295244
295270
  function escrowTotal(pay, spots, legBase, symbol2 = ASK_SYMBOL, sameCoin = true, feeSymbol = FEE_SYMBOL) {
295245
- const leg = legBase / MICRO5;
295271
+ const leg = legBase / MICRO6;
295246
295272
  if (!sameCoin && leg > 0) {
295247
295273
  const total2 = pay * spots;
295248
295274
  return { total: total2, what: `${face(total2, symbol2)} and ${feeWords(legBase * spots, feeSymbol)}. A ${face(pay, symbol2)} reward for each of ${spots} ${spots === 1 ? "answer" : "answers"}, plus ${feeWords(legBase, feeSymbol)} for each review. Held now` };
@@ -295346,11 +295372,9 @@ ${SITE}/t/${earlier.id}`);
295346
295372
  const live = !expert && engineLive();
295347
295373
  const leg = await Promise.resolve().then(() => (init_leg(), leg_exports));
295348
295374
  const legQuote = live ? leg.evaluationLegFor(FEE_DENOM, terms, spots) : null;
295349
- const world = live || expert ? null : await askTheWorldPriced();
295350
- const legBase = expert ? expert.leg : live ? Number(legQuote.base) : world ? world.leg : CHECKER ? leg.checkerLegBase(FEE_DENOM, terms, CHECK_REWARD) : 0;
295351
- const perCheck = expert ? expert.perCheck : world?.perCheck ?? null;
295352
- if (world) terms.judge = { kind: "oracle", address: world.address, rewardUixo: legBase };
295353
- else if (legBase > 0 && terms.judge?.kind === "oracle") terms.judge = { ...terms.judge, rewardUixo: legBase };
295375
+ const legBase = expert ? expert.leg : live ? Number(legQuote.base) : CHECKER ? leg.checkerLegBase(FEE_DENOM, terms, CHECK_REWARD) : 0;
295376
+ const perCheck = expert ? expert.perCheck : null;
295377
+ if (legBase > 0 && terms.judge?.kind === "oracle") terms.judge = { ...terms.judge, rewardUixo: legBase };
295354
295378
  const billing = await Promise.resolve().then(() => (init_reviewBilling(), reviewBilling_exports));
295355
295379
  const escrowed = escrowTotal(pay, spots, legBase, coinSymbol, coin === (expert?.feeDenom ?? FEE_DENOM), symbolOf(expert?.feeDenom ?? FEE_DENOM));
295356
295380
  const total = escrowed.total;
@@ -295387,7 +295411,7 @@ ${SITE}/t/${earlier.id}`);
295387
295411
  * pot covers their price and nobody is ever invoiced. Off, it is our
295388
295412
  * checker and our flat reward, exactly as before.
295389
295413
  */
295390
- checker: expert ? expert.checker.address : live ? ENGINE_ORACLE : world?.address ?? CHECKER,
295414
+ checker: expert ? expert.checker.address : live ? ENGINE_ORACLE : CHECKER,
295391
295415
  checkRewardUixo: legBase,
295392
295416
  /* On the reviewer's own protocol: no rules of the ask's own are minted. */
295393
295417
  ...expert ? { protocol: expert.check.did, feeDenom: expert.feeDenom } : {},
@@ -295679,8 +295703,8 @@ ${SITE}/t/${earlier.id}`);
295679
295703
  const { total, what } = escrowTotal(pay, spots, legBase, coinSymbol, coin === FEE_DENOM);
295680
295704
  const laterEach = follow_pay ? follow_pay * 2 : 0;
295681
295705
  const later = laterEach * spots;
295682
- const laterBase = followUp ? Math.ceil(later * MICRO5 * 1.2) : 0;
295683
- const authorised = laterBase / MICRO5;
295706
+ const laterBase = followUp ? Math.ceil(later * MICRO6 * 1.2) : 0;
295707
+ const authorised = laterBase / MICRO6;
295684
295708
  const whole2 = total + authorised;
295685
295709
  const preview = follow_pay ? `${what}
295686
295710
  plus, after each approval: 2 look-backs \xD7 ${face(follow_pay, coinSymbol)} = up to ${face(later, coinSymbol)} more. Authorised now from this key as ${face(authorised, coinSymbol)} (a fifth on top for headroom), spent only when a cleanup is approved.
@@ -295763,7 +295787,7 @@ All told, escrowed and authorised: ${face(whole2, coinSymbol)}` : what;
295763
295787
  return text4(`Refused: #${collectionId} was posted by ${receipt.owner}, not by ${acting ? `${acting.principal}, the account this key acts for` : `this key (${mine})`}. Only whoever posted an ask can close it and take its money back. Nothing moved.`);
295764
295788
  }
295765
295789
  const plan = await readTakeBack2(collectionId);
295766
- const money3 = (coins) => coins.map((coin) => face(Number(coin.amount) / MICRO5, symbolOf(coin.denom))).join(" and ");
295790
+ const money3 = (coins) => coins.map((coin) => face(Number(coin.amount) / MICRO6, symbolOf(coin.denom))).join(" and ");
295767
295791
  const grantee = acting ? mine : poster;
295768
295792
  const messages = takeBackMsgs2({ owner: poster, grantee, entityDid: receipt.entityDid, collectionId, plan });
295769
295793
  const waiting = plan.waiting === 1 ? "an answer is" : `${plan.waiting} answers are`;
@@ -296121,7 +296145,7 @@ They can disconnect at ${SITE}/connect.`);
296121
296145
  /* Whose money this would spend, and how much of it is left. An agent
296122
296146
  funded by somebody's allowance should be able to say so — and an
296123
296147
  allowance that has run down is the commonest reason a post fails. */
296124
- connection.acting ? `Funded: the account it acts for, within their cap` : FUNDER ? `Funded: ${face(await participant.readAllowanceBase(FUNDER, mine) / MICRO5, ASK_SYMBOL)} left of ${FUNDER.slice(0, 14)}\u2026's allowance` : `Funded: its own balance. Nobody has granted this key an allowance`,
296148
+ connection.acting ? `Funded: the account it acts for, within their cap` : FUNDER ? `Funded: ${face(await participant.readAllowanceBase(FUNDER, mine) / MICRO6, ASK_SYMBOL)} left of ${FUNDER.slice(0, 14)}\u2026's allowance` : `Funded: its own balance. Nobody has granted this key an allowance`,
296125
296149
  payWords2(connection.acting !== null, home, held),
296126
296150
  /* A key that holds nothing and has no allowance behind it cannot post.
296127
296151
  Say where money comes from, in order, before a model finds out by
@@ -296577,7 +296601,7 @@ Then call post_call again. Nothing was posted.`);
296577
296601
  if (typeof words5 !== "string") return text4(`Refused: ${words5.refused}. Nothing was posted.`);
296578
296602
  if (!confirm) return text4([`Call "${slug}" is ${order2.length} asks: ${order2.map((one) => LEG_WORDS[one]).join(", then ")}.`, ...moneySentence ? [moneySentence] : [], words5].join("\n"));
296579
296603
  if (confirm.trim() !== payDraft.confirmToken(quote)) return text4(`Refused: confirm said "${confirm}" but the person pays ${payDraft.confirmToken(quote)}. Preview it again.`);
296580
- const terms = { slug, fields: draft.fields, dates: plan.dates, legs: plan.legs, checker: checker.address, perCheck, ...sponsor ? { sponsor } : {} };
296604
+ const terms = { slug, fields: draft.fields, dates: plan.dates, legs: plan.legs, checker: checker.address, perCheck, ...checker.fee ? { fee: checker.fee } : {}, ...plan.share ? { share: plan.share } : {}, ...sponsor ? { sponsor } : {} };
296581
296605
  return text4(await payDraft.saveDraft(SITE, { kind: "call", terms, quote, network: NETWORK2 }, fetch2));
296582
296606
  }
296583
296607
  if (!confirm) {
@@ -296618,7 +296642,7 @@ Then call post_call again. Nothing was posted.`);
296618
296642
  site: SITE
296619
296643
  });
296620
296644
  if (refusedBefore) return text4(refusedBefore);
296621
- const room = dayRoom("call", leg.escrowBase / MICRO5);
296645
+ const room = dayRoom("call", leg.escrowBase / MICRO6);
296622
296646
  if (room) return text4(room);
296623
296647
  const key = await loadKey2();
296624
296648
  let posted;
@@ -296635,7 +296659,7 @@ Then call post_call again. Nothing was posted.`);
296635
296659
  approver,
296636
296660
  mnemonic: key.mnemonic,
296637
296661
  nudge: (event, id) => nudge(event, id, checker.at),
296638
- charge: (escrowBase) => chargeDay("call", escrowBase / MICRO5),
296662
+ charge: (escrowBase) => chargeDay("call", escrowBase / MICRO6),
296639
296663
  feeSplit: split3,
296640
296664
  sponsor
296641
296665
  });
@@ -297323,7 +297347,7 @@ Open the profile and the evidence. Decline with decide_check. Approving happens
297323
297347
  async function priceOf2(plan, world, coin) {
297324
297348
  const { planCost: planCost2, planAnswerCount: planAnswerCount2 } = await Promise.resolve().then(() => (init_marketPlan(), marketPlan_exports));
297325
297349
  const sameCoin = FEE_DENOM === coin;
297326
- return { cost: planCost2(plan, { reviewUsd: sameCoin ? world.leg / MICRO5 : 0, feeRate: 0 }), reviewsBase: sameCoin ? 0 : world.leg * planAnswerCount2(plan) };
297350
+ return { cost: planCost2(plan, { reviewUsd: sameCoin ? world.leg / MICRO6 : 0, feeRate: 0 }), reviewsBase: sameCoin ? 0 : world.leg * planAnswerCount2(plan) };
297327
297351
  }
297328
297352
  async function reviewWords(world, reviewsBase) {
297329
297353
  if (world.perCheck) return `Review fee: ${(await Promise.resolve().then(() => (init_reviewBilling(), reviewBilling_exports))).creditsCopy(null, feeWords(world.perCheck.price))}`;
@@ -297370,7 +297394,7 @@ Open the profile and the evidence. Decline with decide_check. Approving happens
297370
297394
  SIGNAL_GUIDE2,
297371
297395
  "",
297372
297396
  draftingRules2(
297373
- { perAskUsd: MAX_PER_ASK > 0 ? MAX_PER_ASK : 5, reviewUsd: world && FEE_DENOM === ASK_DENOM ? world.leg / MICRO5 : 0 },
297397
+ { perAskUsd: MAX_PER_ASK > 0 ? MAX_PER_ASK : 5, reviewUsd: world && FEE_DENOM === ASK_DENOM ? world.leg / MICRO6 : 0 },
297374
297398
  (amount3) => face(amount3, ASK_SYMBOL),
297375
297399
  "dollars"
297376
297400
  ),
@@ -297530,7 +297554,7 @@ Open the profile and the evidence. Decline with decide_check. Approving happens
297530
297554
  if (otherCoin) return text4(`Refused: ${otherCoin}. Draft the plan again with draft_plan in that coin. Nothing was posted.`);
297531
297555
  if (acting) {
297532
297556
  const left = acting.cap && acting.cap.denom === coin ? Number(acting.cap.remainingBase) : 0;
297533
- if (left < baseFromPay2(cost.totalUsd)) return text4(`Refused: ${acting.principal}'s cap for this key has ${money3(left / MICRO5)} left, and the plan escrows ${money3(cost.totalUsd)}. They raise it at ${SITE}/connect. Nothing was posted.`);
297557
+ if (left < baseFromPay2(cost.totalUsd)) return text4(`Refused: ${acting.principal}'s cap for this key has ${money3(left / MICRO6)} left, and the plan escrows ${money3(cost.totalUsd)}. They raise it at ${SITE}/connect. Nothing was posted.`);
297534
297558
  }
297535
297559
  const approval = await askThePerson(
297536
297560
  server2.server,
@@ -297626,7 +297650,7 @@ Open the profile and the evidence. Decline with decide_check. Approving happens
297626
297650
  if (!status?.list) return text4(`No plan ${slug} on this deployment.`);
297627
297651
  if (status.funder !== poster) return text4(`Refused: plan ${slug} was posted by ${status.funder}, not by ${acting ? `${acting.principal}, the account this key acts for` : `this key (${mine})`}. Nothing moved.`);
297628
297652
  const ids = status.list.map((one) => one.collectionId).filter((one) => Boolean(one));
297629
- const coins = (list7) => list7.map((coin) => face(Number(coin.amount) / MICRO5, symbolOf(coin.denom))).join(" and ");
297653
+ const coins = (list7) => list7.map((coin) => face(Number(coin.amount) / MICRO6, symbolOf(coin.denom))).join(" and ");
297630
297654
  const lines2 = [];
297631
297655
  let left = 0;
297632
297656
  let actor = null;