@ixo/asks-mcp 2.0.0-dev.1 → 2.0.0-dev.3

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 +566 -223
  2. package/package.json +1 -1
package/dist/asks-mcp.mjs CHANGED
@@ -7508,7 +7508,7 @@ function reviewSlugOf(facts) {
7508
7508
  function askPage(site, collectionId, facts) {
7509
7509
  const base6 = site.replace(/\/+$/, "");
7510
7510
  const review = reviewSlugOf(facts);
7511
- if (review) return `${base6}/pro/reviews/${collectionId}`;
7511
+ if (review) return `${base6}/me/pro-asks/${collectionId}`;
7512
7512
  const slug = facts.slug ?? (facts.campaign ? slugOfTag(facts.campaign) : null);
7513
7513
  return slug ? `${base6}/opencall/${slug}` : `${base6}/t/${collectionId}`;
7514
7514
  }
@@ -7518,7 +7518,10 @@ function answerPage(site, collectionId, claimId, facts) {
7518
7518
  return review ? `${base6}/pro/reviews/${collectionId}/report/${encodeURIComponent(claimId)}` : `${base6}/r/${collectionId}/trace/${encodeURIComponent(claimId)}`;
7519
7519
  }
7520
7520
  function inviteLink(site, token, review) {
7521
- return review ? `${site.replace(/\/+$/, "")}/pro/i/${token}` : `${site.replace(/\/+$/, "")}/opencall/i/${token}`;
7521
+ return review ? `${site.replace(/\/+$/, "")}/i/${token}` : `${site.replace(/\/+$/, "")}/opencall/i/${token}`;
7522
+ }
7523
+ function sitePath(path) {
7524
+ return path.replace(/^\/pro\/reviews\/([^/?#]+)\/with\//, "/me/pro-asks/$1/with/").replace(/^\/pro\/reviews\/([^/?#]+)$/, "/me/pro-asks/$1").replace(/^\/pro\/work(?=\/|$)/, "/me/work").replace(/^\/pro\/i\//, "/i/").replace(/^\/pro\/pros(?=\/|$)/, "/pros");
7522
7525
  }
7523
7526
  var isReviewTitle, proPage, roomPage;
7524
7527
  var init_world = __esm({
@@ -7526,8 +7529,8 @@ var init_world = __esm({
7526
7529
  "use strict";
7527
7530
  init_callTag();
7528
7531
  isReviewTitle = (title) => /^Expert review:/.test(title ?? "");
7529
- proPage = (site, handle2) => `${site.replace(/\/+$/, "")}/pro/pros/${handle2}`;
7530
- roomPage = (site, collectionId, pro) => `${site.replace(/\/+$/, "")}/pro/reviews/${collectionId}/with/${encodeURIComponent(pro.replace(/^@/, ""))}`;
7532
+ proPage = (site, handle2) => `${site.replace(/\/+$/, "")}/pros/${handle2}`;
7533
+ roomPage = (site, collectionId, pro) => `${site.replace(/\/+$/, "")}/me/pro-asks/${collectionId}/with/${encodeURIComponent(pro.replace(/^@/, ""))}`;
7531
7534
  }
7532
7535
  });
7533
7536
 
@@ -8093,18 +8096,18 @@ function formAnswersOf(envelope) {
8093
8096
  for (const key of keys) {
8094
8097
  const value = doc[key];
8095
8098
  const isFiles = Array.isArray(value) && value.every((one) => one && typeof one === "object" && typeof one.name === "string");
8096
- const said3 = isFiles ? value.map((one) => one.name).join(", ") : typeof value === "boolean" ? value ? "yes" : "no" : typeof value === "string" || typeof value === "number" ? String(value) : null;
8097
- if (said3 === null) return null;
8098
- let found = deliverable.indexOf(`: ${said3}`, at);
8099
- while (found !== -1 && !(found + 2 + said3.length === deliverable.length || deliverable[found + 2 + said3.length] === "\n")) found = deliverable.indexOf(`: ${said3}`, found + 1);
8099
+ const said4 = isFiles ? value.map((one) => one.name).join(", ") : typeof value === "boolean" ? value ? "yes" : "no" : typeof value === "string" || typeof value === "number" ? String(value) : null;
8100
+ if (said4 === null) return null;
8101
+ let found = deliverable.indexOf(`: ${said4}`, at);
8102
+ while (found !== -1 && !(found + 2 + said4.length === deliverable.length || deliverable[found + 2 + said4.length] === "\n")) found = deliverable.indexOf(`: ${said4}`, found + 1);
8100
8103
  if (found === -1) return null;
8101
8104
  const label = deliverable.slice(at, found).trim();
8102
8105
  if (!label || label.includes("\n")) return null;
8103
- at = found + 2 + said3.length + 1;
8106
+ at = found + 2 + said4.length + 1;
8104
8107
  if (isFiles) {
8105
8108
  const files = value.filter((one) => isStoredFile(one.content)).map((one) => ({ name: one.name.replace(/\s+/g, " ").trim().slice(0, 80) || "file", mediaType: typeof one.type === "string" ? one.type.slice(0, 80) : "application/octet-stream", url: one.content }));
8106
8109
  out.push({ label, files });
8107
- } else out.push({ label, value: said3 });
8110
+ } else out.push({ label, value: said4 });
8108
8111
  }
8109
8112
  return at >= deliverable.length ? out : null;
8110
8113
  }
@@ -8429,24 +8432,24 @@ function blockOf(raw) {
8429
8432
  return null;
8430
8433
  }
8431
8434
  function callOf(raw) {
8432
- const call2 = raw;
8433
- if (!call2 || typeof call2 !== "object") return null;
8435
+ const call3 = raw;
8436
+ if (!call3 || typeof call3 !== "object") return null;
8434
8437
  const L4 = CALL_LIMITS;
8435
- if (typeof call2.slug !== "string" || !CALL_SLUG.test(call2.slug)) return null;
8436
- if (!CALL_LEGS.includes(call2.leg)) return null;
8437
- if (!line(call2.title, L4.title) || !line(call2.lede, L4.lede) || !line(call2.poster, L4.poster)) return null;
8438
- 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;
8439
- const money2 = call2.money;
8438
+ if (typeof call3.slug !== "string" || !CALL_SLUG.test(call3.slug)) return null;
8439
+ if (!CALL_LEGS.includes(call3.leg)) return null;
8440
+ if (!line(call3.title, L4.title) || !line(call3.lede, L4.lede) || !line(call3.poster, L4.poster)) return null;
8441
+ if (!Array.isArray(call3.points) || call3.points.length === 0 || call3.points.length > L4.lines || !call3.points.every((one) => finite(one) && one >= 0 && one <= 100)) return null;
8442
+ const money2 = call3.money;
8440
8443
  if (!money2 || typeof money2 !== "object") return null;
8441
8444
  if (!amount(money2.prize) || !whole(money2.runnersN, 0, 5) || !amount(money2.runnersEach) || !amount(money2.entryEach) || !whole(money2.entryUpTo, 1, 1e4)) return null;
8442
- const share = call2.share;
8445
+ const share = call3.share;
8443
8446
  if (share !== void 0 && (!share || typeof share !== "object" || !nonNegative(share.network) || !nonNegative(share.node) || share.network + share.node >= 100)) return null;
8444
- const named = call2.sponsor;
8447
+ const named = call3.sponsor;
8445
8448
  const sponsor = named && typeof named === "object" && typeof named.slug === "string" && CALL_SLUG.test(named.slug) && line(named.name, L4.sponsorName) && typeof named.node === "string" && ENTITY_DID.test(named.node) ? named : void 0;
8446
- if (!date5(call2.closes) || !date5(call2.drop) || !date5(call2.pick)) return null;
8449
+ if (!date5(call3.closes) || !date5(call3.drop) || !date5(call3.pick)) return null;
8447
8450
  let legs;
8448
- if (call2.legs !== void 0) {
8449
- const raw2 = call2.legs;
8451
+ if (call3.legs !== void 0) {
8452
+ const raw2 = call3.legs;
8450
8453
  if (!raw2 || typeof raw2 !== "object") return null;
8451
8454
  legs = {};
8452
8455
  for (const name8 of CALL_LEGS) {
@@ -8456,42 +8459,42 @@ function callOf(raw) {
8456
8459
  legs[name8] = id;
8457
8460
  }
8458
8461
  }
8459
- if (!Array.isArray(call2.blocks) || call2.blocks.length > L4.blocks) return null;
8460
- const blocks = call2.blocks.map(blockOf);
8462
+ if (!Array.isArray(call3.blocks) || call3.blocks.length > L4.blocks) return null;
8463
+ const blocks = call3.blocks.map(blockOf);
8461
8464
  if (blocks.some((block2) => block2 === null)) return null;
8462
8465
  let review = null;
8463
- if (call2.kind !== void 0) {
8464
- if (call2.kind !== "review" || call2.mode !== "hire") return null;
8465
- const subject = call2.subject;
8466
+ if (call3.kind !== void 0) {
8467
+ if (call3.kind !== "review" || call3.mode !== "hire") return null;
8468
+ const subject = call3.subject;
8466
8469
  if (subject !== void 0) {
8467
8470
  if (!subject || typeof subject !== "object" || !line(subject.name, L4.subjectName)) return null;
8468
8471
  if (subject.version !== void 0 && !line(subject.version, L4.version)) return null;
8469
8472
  if (subject.where !== void 0 && !line(subject.where, L4.where)) return null;
8470
8473
  }
8471
- 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;
8474
+ if (call3.scenarios !== void 0 && (!Array.isArray(call3.scenarios) || call3.scenarios.length === 0 || call3.scenarios.length > L4.scenarios || !call3.scenarios.every((one) => line(one, L4.scenario)))) return null;
8472
8475
  review = {
8473
8476
  kind: "review",
8474
8477
  ...subject ? { subject: { name: subject.name, ...subject.version !== void 0 ? { version: subject.version } : {}, ...subject.where !== void 0 ? { where: subject.where } : {} } } : {},
8475
- ...call2.scenarios !== void 0 ? { scenarios: [...call2.scenarios] } : {}
8478
+ ...call3.scenarios !== void 0 ? { scenarios: [...call3.scenarios] } : {}
8476
8479
  };
8477
8480
  }
8478
8481
  return {
8479
8482
  call: {
8480
- slug: call2.slug,
8481
- leg: call2.leg,
8483
+ slug: call3.slug,
8484
+ leg: call3.leg,
8482
8485
  /* The one literal: anything else is a competition, as every call before it was. */
8483
- ...call2.mode === "hire" ? { mode: "hire" } : {},
8486
+ ...call3.mode === "hire" ? { mode: "hire" } : {},
8484
8487
  ...review ?? {},
8485
- title: call2.title,
8486
- lede: call2.lede,
8487
- poster: call2.poster,
8488
- points: [...call2.points],
8488
+ title: call3.title,
8489
+ lede: call3.lede,
8490
+ poster: call3.poster,
8491
+ points: [...call3.points],
8489
8492
  money: { prize: money2.prize, runnersN: money2.runnersN, runnersEach: money2.runnersEach, entryEach: money2.entryEach, entryUpTo: money2.entryUpTo },
8490
8493
  ...share ? { share: { network: share.network, node: share.node } } : {},
8491
8494
  ...sponsor ? { sponsor: { slug: sponsor.slug, name: sponsor.name, node: sponsor.node } } : {},
8492
- closes: call2.closes,
8493
- drop: call2.drop,
8494
- pick: call2.pick,
8495
+ closes: call3.closes,
8496
+ drop: call3.drop,
8497
+ pick: call3.pick,
8495
8498
  ...legs ? { legs } : {},
8496
8499
  blocks
8497
8500
  }
@@ -9080,7 +9083,7 @@ function toEngineRubric(terms, binding, options = {}) {
9080
9083
  const screens = [];
9081
9084
  if (PHOTOGRAPH.has(normalized.deliverable.type)) {
9082
9085
  const photos = pair && !normalized.site ? [PHOTO, BEFORE_PHOTO] : [PHOTO];
9083
- const said3 = (photo) => photos.length === 1 ? "The photograph" : photo === BEFORE_PHOTO ? "The before photograph" : "The after photograph";
9086
+ const said4 = (photo) => photos.length === 1 ? "The photograph" : photo === BEFORE_PHOTO ? "The before photograph" : "The after photograph";
9084
9087
  const screened2 = (sourced) => {
9085
9088
  pending.push(sourced);
9086
9089
  screens.push({ ...sourced.gate, when: extRef(sourced.name) });
@@ -9090,7 +9093,7 @@ function toEngineRubric(terms, binding, options = {}) {
9090
9093
  screened2({
9091
9094
  name: PHOTO_CHECKS.notMarkedGenerated,
9092
9095
  send: { photo },
9093
- gate: { "@type": "Gate", code: codeFor(extra, "not-generated"), reason: `${said3(photo)} says of itself that an AI generator made it`, onFail: "reject", class: "invalid_evidence" }
9096
+ gate: { "@type": "Gate", code: codeFor(extra, "not-generated"), reason: `${said4(photo)} says of itself that an AI generator made it`, onFail: "reject", class: "invalid_evidence" }
9094
9097
  });
9095
9098
  }
9096
9099
  const judged = normalized.criteria.filter((criterion) => criterion.kind === "judge").length;
@@ -9117,7 +9120,7 @@ function toEngineRubric(terms, binding, options = {}) {
9117
9120
  gate: {
9118
9121
  "@type": "Gate",
9119
9122
  code: codeFor(extra, "not-elsewhere"),
9120
- reason: `${said3(photo)}'s own GPS puts it far from the place reported. Take the photograph at the place you are reporting`,
9123
+ reason: `${said4(photo)}'s own GPS puts it far from the place reported. Take the photograph at the place you are reporting`,
9121
9124
  onFail: "reject",
9122
9125
  class: "invalid_evidence"
9123
9126
  }
@@ -9812,6 +9815,13 @@ var init_gateMet = __esm({
9812
9815
  });
9813
9816
 
9814
9817
  // ../../packages/openhands-sdk/src/data/engineUrl.ts
9818
+ var engineUrl_exports = {};
9819
+ __export(engineUrl_exports, {
9820
+ engineConfigured: () => engineConfigured,
9821
+ engineIssuerKeysUrl: () => engineIssuerKeysUrl,
9822
+ engineReceiptUrl: () => engineReceiptUrl,
9823
+ engineUrl: () => engineUrl
9824
+ });
9815
9825
  var engineUrl, engineConfigured, engineReceiptUrl, engineIssuerKeysUrl;
9816
9826
  var init_engineUrl = __esm({
9817
9827
  "../../packages/openhands-sdk/src/data/engineUrl.ts"() {
@@ -10087,8 +10097,8 @@ var init_engine = __esm({
10087
10097
  num = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
10088
10098
  obj2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
10089
10099
  withPerson = (gate, verdict, reasonCodes) => {
10090
- const said3 = personGate(gate.code, verdict, reasonCodes);
10091
- return said3 ? { ...gate, ...said3, joined: true } : gate;
10100
+ const said4 = personGate(gate.code, verdict, reasonCodes);
10101
+ return said4 ? { ...gate, ...said4, joined: true } : gate;
10092
10102
  };
10093
10103
  codesOf = (raw) => Array.isArray(raw) ? raw.filter((one) => typeof one === "string") : [];
10094
10104
  engineStatusOf = (decision) => decision.outcome ?? (decision.verdict === "approve" || decision.verdict === "partial" ? 1 : decision.verdict === "reject" ? 2 : 5);
@@ -28345,18 +28355,18 @@ function waysIn(org, oracle, sourceId) {
28345
28355
  `In Claude Code: eval-oracle api review-billing enable --source ${sourceId ?? "<source id>"} --kit ${oracle.url.replace(/\/$/, "")} --cap <dollars> (it previews first; add --yes to sign).`
28346
28356
  ];
28347
28357
  }
28348
- async function sourceCall(oracleUrl2, audience, mint, call2, options = {}) {
28358
+ async function sourceCall(oracleUrl2, audience, mint, call3, options = {}) {
28349
28359
  try {
28350
- const response = await (options.fetch ?? fetch)(`${base3(oracleUrl2)}${call2.path}`, {
28351
- method: call2.method ?? "GET",
28360
+ const response = await (options.fetch ?? fetch)(`${base3(oracleUrl2)}${call3.path}`, {
28361
+ method: call3.method ?? "GET",
28352
28362
  headers: {
28353
28363
  accept: "application/json",
28354
- authorization: `Bearer ${await mint(audience, call2.can, call2.sourceId)}`,
28364
+ authorization: `Bearer ${await mint(audience, call3.can, call3.sourceId)}`,
28355
28365
  "x-auth-type": "ucan",
28356
- ...call2.sourceId ? { "x-source-id": call2.sourceId } : {},
28357
- ...call2.body !== void 0 ? { "content-type": "application/json" } : {}
28366
+ ...call3.sourceId ? { "x-source-id": call3.sourceId } : {},
28367
+ ...call3.body !== void 0 ? { "content-type": "application/json" } : {}
28358
28368
  },
28359
- ...call2.body !== void 0 ? { body: JSON.stringify(call2.body) } : {},
28369
+ ...call3.body !== void 0 ? { body: JSON.stringify(call3.body) } : {},
28360
28370
  signal: AbortSignal.timeout(TIMEOUT2)
28361
28371
  });
28362
28372
  const body = await response.json().catch(() => null);
@@ -28554,8 +28564,8 @@ function parseChecks(raw) {
28554
28564
  return raw.flatMap((one) => {
28555
28565
  const c = one;
28556
28566
  if (!c || typeof c.name !== "string" || c.status !== "ok" && c.status !== "error") return [];
28557
- const said3 = typeof c.reason === "string" ? c.reason.trim() : "";
28558
- return [{ name: c.name, status: c.status, value: c.value ?? null, reason: said3 ? said3.length > REASON_MAX ? `${said3.slice(0, REASON_MAX).trimEnd()}\u2026` : said3 : null }];
28567
+ const said4 = typeof c.reason === "string" ? c.reason.trim() : "";
28568
+ return [{ name: c.name, status: c.status, value: c.value ?? null, reason: said4 ? said4.length > REASON_MAX ? `${said4.slice(0, REASON_MAX).trimEnd()}\u2026` : said4 : null }];
28559
28569
  });
28560
28570
  }
28561
28571
  function parseReviewerNote(raw) {
@@ -29605,8 +29615,8 @@ function fileAnswers(files, urlOf = ipfsDocUrl) {
29605
29615
  };
29606
29616
  }
29607
29617
  function extensionOf(type) {
29608
- const bare = (type ?? "").toLowerCase().split(";")[0]?.trim() ?? "";
29609
- switch (bare) {
29618
+ const bare2 = (type ?? "").toLowerCase().split(";")[0]?.trim() ?? "";
29619
+ switch (bare2) {
29610
29620
  case "image/jpeg":
29611
29621
  return ".jpg";
29612
29622
  case "image/png":
@@ -29696,14 +29706,14 @@ function rulesOf(rubric, manifest) {
29696
29706
  const work = manifest && typeof manifest === "object" ? manifest : {};
29697
29707
  const ai = listOf(rub.aiChecks).length ? listOf(rub.aiChecks) : listOf(work.ai && typeof work.ai === "object" ? Object.values(work.ai) : []);
29698
29708
  const tasks = listOf(rub.review?.tasks).length ? listOf(rub.review?.tasks) : listOf(work.review?.taskDetails);
29699
- const said3 = (kind) => (raw) => {
29709
+ const said4 = (kind) => (raw) => {
29700
29710
  const text4 = clampText(raw, 300);
29701
29711
  return text4 ? [{ text: text4, kind }] : [];
29702
29712
  };
29703
29713
  return [
29704
- ...listOf(rub.gates).flatMap((gate) => said3("measure")(gate.reason)),
29705
- ...ai.flatMap((check2) => (Array.isArray(check2.instructions) ? check2.instructions : []).flatMap(said3("judge"))),
29706
- ...tasks.flatMap((task) => said3("attest")(task.prompt))
29714
+ ...listOf(rub.gates).flatMap((gate) => said4("measure")(gate.reason)),
29715
+ ...ai.flatMap((check2) => (Array.isArray(check2.instructions) ? check2.instructions : []).flatMap(said4("judge"))),
29716
+ ...tasks.flatMap((task) => said4("attest")(task.prompt))
29707
29717
  ].slice(0, RULES_MAX);
29708
29718
  }
29709
29719
  async function readProven(resource2, fetchImpl) {
@@ -30053,7 +30063,7 @@ function checkEnvelope(input) {
30053
30063
  if (problems.length) throw new Error(problems.join(" "));
30054
30064
  const answered = input.fields.filter((field2) => !isEmpty2(input.values[field2.name]));
30055
30065
  const answers = Object.fromEntries(answered.map((field2) => [field2.name, answerOf(field2, input.values[field2.name])]));
30056
- const said3 = (field2) => {
30066
+ const said4 = (field2) => {
30057
30067
  const value = input.values[field2.name];
30058
30068
  if (field2.type === "file") return filesOf(value).map((file3) => file3.name).join(", ");
30059
30069
  if (field2.type === "boolean") return value ? "yes" : "no";
@@ -30067,7 +30077,7 @@ function checkEnvelope(input) {
30067
30077
  ...input.delegate ? { delegate: input.delegate } : {},
30068
30078
  ...input.alias ? { alias: input.alias } : {},
30069
30079
  ...input.via ? { via: input.via } : {},
30070
- deliverable: answered.map((field2) => `${field2.label}: ${said3(field2)}`).join("\n"),
30080
+ deliverable: answered.map((field2) => `${field2.label}: ${said4(field2)}`).join("\n"),
30071
30081
  /* Last: a form question that shares an envelope field's name keeps the person's answer, which is what the checker reads. */
30072
30082
  ...answers
30073
30083
  };
@@ -250658,10 +250668,10 @@ var require_get_proto = __commonJS({
250658
250668
  var require_hasown = __commonJS({
250659
250669
  "../../node_modules/.pnpm/hasown@2.0.4/node_modules/hasown/index.js"(exports, module) {
250660
250670
  "use strict";
250661
- var call2 = Function.prototype.call;
250671
+ var call3 = Function.prototype.call;
250662
250672
  var $hasOwn = Object.prototype.hasOwnProperty;
250663
250673
  var bind2 = require_function_bind();
250664
- module.exports = bind2.call(call2, $hasOwn);
250674
+ module.exports = bind2.call(call3, $hasOwn);
250665
250675
  }
250666
250676
  });
250667
250677
 
@@ -260049,8 +260059,8 @@ async function uploadToLane(bytes3, contentType3, args) {
260049
260059
  signal: args.signal ?? AbortSignal.timeout(6e4)
260050
260060
  });
260051
260061
  if (!response.ok) {
260052
- const said3 = await response.text().catch(() => "");
260053
- throw new LaneRefused(response.status, `the private store refused the file (${response.status}${said3 ? `: ${said3.slice(0, 160)}` : ""})`);
260062
+ const said4 = await response.text().catch(() => "");
260063
+ throw new LaneRefused(response.status, `the private store refused the file (${response.status}${said4 ? `: ${said4.slice(0, 160)}` : ""})`);
260054
260064
  }
260055
260065
  const meta4 = await response.json();
260056
260066
  if (typeof meta4.cid !== "string" || !meta4.cid) throw new LaneRefused(502, "the private store gave no address for the file");
@@ -260327,8 +260337,8 @@ async function allowOperatorAmounts(collectionId, owner, options) {
260327
260337
  signal: AbortSignal.timeout(1e4)
260328
260338
  });
260329
260339
  if (response.ok) return { ok: true };
260330
- const said3 = await response.json().catch(() => null) ?? null;
260331
- const message = typeof said3?.error === "string" ? said3.error : said3?.error?.message ?? said3?.message ?? "";
260340
+ const said4 = await response.json().catch(() => null) ?? null;
260341
+ const message = typeof said4?.error === "string" ? said4.error : said4?.error?.message ?? said4?.message ?? "";
260332
260342
  why = `the oracle answered ${response.status}${message ? ` (${String(message).slice(0, 160)})` : ""}`;
260333
260343
  if (response.status === 401 || response.status === 403 || response.status === 400) break;
260334
260344
  } catch (error54) {
@@ -260757,9 +260767,9 @@ function dominantWaste(wastes) {
260757
260767
  }
260758
260768
  function wastesOf(assessment) {
260759
260769
  if (!assessment) return [];
260760
- const said3 = Array.isArray(assessment.wastes) && assessment.wastes.length > 0 ? assessment.wastes : [assessment.waste];
260770
+ const said4 = Array.isArray(assessment.wastes) && assessment.wastes.length > 0 ? assessment.wastes : [assessment.waste];
260761
260771
  const kept = [];
260762
- for (const key of ORDERED_WASTE) if (said3.includes(key) && !kept.includes(key)) kept.push(key);
260772
+ for (const key of ORDERED_WASTE) if (said4.includes(key) && !kept.includes(key)) kept.push(key);
260763
260773
  return kept;
260764
260774
  }
260765
260775
  function listSays(wastes) {
@@ -261565,8 +261575,8 @@ function broadcastTimeoutId(error54) {
261565
261575
  const txId = error54.txId;
261566
261576
  if (typeof txId !== "string" || !txId) return null;
261567
261577
  const named = error54.name === "TimeoutError";
261568
- const said3 = /was submitted but was not yet found on the chain/i.test(String(error54.message ?? ""));
261569
- return named || said3 ? txId : null;
261578
+ const said4 = /was submitted but was not yet found on the chain/i.test(String(error54.message ?? ""));
261579
+ return named || said4 ? txId : null;
261570
261580
  }
261571
261581
  function refusedAtCheckTx(error54) {
261572
261582
  if (!error54 || typeof error54 !== "object") return false;
@@ -263205,7 +263215,7 @@ function ledeOf(trace) {
263205
263215
  }
263206
263216
  function gatheredDetail(checks) {
263207
263217
  const ext = checks.filter((check2) => check2.kind === "ext");
263208
- const named = [...new Set(ext.map((check2) => words3(check2.name)).filter((said3) => Boolean(said3)))];
263218
+ const named = [...new Set(ext.map((check2) => words3(check2.name)).filter((said4) => Boolean(said4)))];
263209
263219
  const unknown3 = ext.filter((check2) => !words3(check2.name)).length;
263210
263220
  const measured = unknown3 ? [...named, unknown3 === 1 ? "one other thing" : `${unknown3} other things`] : named;
263211
263221
  const duplicates = checks.some((check2) => check2.kind === "unique");
@@ -263241,8 +263251,8 @@ function rulesSummary(rules, verdict) {
263241
263251
  const unreached = total - met - failed;
263242
263252
  if (!total) return verdict === "approve" ? "Approved against rules fixed before the work began." : "Decided against rules fixed before the work began.";
263243
263253
  if (!failed && !unreached) return `${met} of ${total} ${total === 1 ? "rule" : "rules"} met, against rules fixed before the work began.`;
263244
- const said3 = [`${met} met`, `${failed} not met`, ...unreached ? [`${unreached} not reached`] : []];
263245
- return `Of ${total} rules, ${list6(said3)}.`;
263254
+ const said4 = [`${met} met`, `${failed} not met`, ...unreached ? [`${unreached} not reached`] : []];
263255
+ return `Of ${total} rules, ${list6(said4)}.`;
263246
263256
  }
263247
263257
  function signedDetail(step) {
263248
263258
  const host = issuerHost(step.issuer);
@@ -263314,8 +263324,8 @@ function sentence3(step) {
263314
263324
  return `${face ? `${face.text} released` : "released"} to ${step.to}. ${paidDetail(step)}${fee}`;
263315
263325
  }
263316
263326
  case "recorded": {
263317
- const said3 = recordedLine(step.status);
263318
- return `${said3.line}. ${said3.detail}`;
263327
+ const said4 = recordedLine(step.status);
263328
+ return `${said4.line}. ${said4.detail}`;
263319
263329
  }
263320
263330
  }
263321
263331
  }
@@ -263362,23 +263372,23 @@ function lineSentence(line2) {
263362
263372
  if (sentence4.length > 300) throw new Error(`a judged line is ${sentence4.length} characters with its failure; the jury reads 300 at most`);
263363
263373
  return sentence4;
263364
263374
  }
263365
- function legCall(call2, leg) {
263366
- const read9 = callOf({ ...call2, leg });
263375
+ function legCall(call3, leg) {
263376
+ const read9 = callOf({ ...call3, leg });
263367
263377
  if (!read9) throw new Error("the call does not read back: a field is missing, too long, or not an https address");
263368
263378
  return read9.call;
263369
263379
  }
263370
263380
  function taskFor(title, leg, kind) {
263371
263381
  const named = title.replace(/\s+/g, " ").trim();
263372
- const said3 = leg === "entries" ? `${kind === "review" ? "Expert review" : "Open call"}: ${named}` : leg === "prize" ? `The pick of the open call: ${named}` : `A runner-up of the open call: ${named}`;
263373
- return said3.length <= 140 ? said3 : `${said3.slice(0, 139)}\u2026`;
263382
+ const said4 = leg === "entries" ? `${kind === "review" ? "Expert review" : "Open call"}: ${named}` : leg === "prize" ? `The pick of the open call: ${named}` : `A runner-up of the open call: ${named}`;
263383
+ return said4.length <= 140 ? said4 : `${said4.slice(0, 139)}\u2026`;
263374
263384
  }
263375
263385
  function callEntriesTerms(input) {
263376
263386
  if (input.lines.length !== CALL_LIMITS.lines) throw new Error(`a call is judged on exactly ${CALL_LIMITS.lines} lines`);
263377
263387
  if (input.judge.kind !== "oracle" || !input.judge.address) throw new Error("the entries are judged by the oracle, and it has to be named");
263378
- const call2 = legCall(input.call, "entries");
263379
- if (call2.points.length !== CALL_LIMITS.lines) throw new Error("one score per judged line");
263380
- if (call2.kind === "review" && !input.report) throw new Error("a review call's entries are reports: say report (the extra sections, or none)");
263381
- if (call2.kind !== "review" && input.report) throw new Error("only a review call is answered as a report");
263388
+ const call3 = legCall(input.call, "entries");
263389
+ if (call3.points.length !== CALL_LIMITS.lines) throw new Error("one score per judged line");
263390
+ if (call3.kind === "review" && !input.report) throw new Error("a review call's entries are reports: say report (the extra sections, or none)");
263391
+ if (call3.kind !== "review" && input.report) throw new Error("only a review call is answered as a report");
263382
263392
  if (input.approver !== void 0 && !/^ixo1[a-z0-9]{38,64}$/.test(input.approver)) throw new Error("approver is an ixo1 address");
263383
263393
  const criteria = [
263384
263394
  { id: "present", kind: "measure", gate: { id: "non-empty" } },
@@ -263387,11 +263397,11 @@ function callEntriesTerms(input) {
263387
263397
  ];
263388
263398
  const terms = {
263389
263399
  v: 2,
263390
- task: taskFor(call2.title, "entries", call2.kind),
263400
+ task: taskFor(call3.title, "entries", call3.kind),
263391
263401
  deliverable: { type: "text", prompt: input.report ? REVIEW_DELIVERABLE_PROMPT : "One page, in your own words, covering all five requirements" },
263392
- campaign: callTag(call2.slug),
263402
+ campaign: callTag(call3.slug),
263393
263403
  ...input.access ? { access: input.access } : {},
263394
- call: call2,
263404
+ call: call3,
263395
263405
  criteria,
263396
263406
  judge: input.judge,
263397
263407
  ...input.approver ? { approver: input.approver } : {}
@@ -263399,17 +263409,17 @@ function callEntriesTerms(input) {
263399
263409
  return input.report ? withReport(terms, input.report, input.approver ? { v: 2 } : void 0) : terms;
263400
263410
  }
263401
263411
  function callPickTerms(input) {
263402
- const call2 = legCall(input.call, input.leg);
263403
- if (call2.mode === "hire") throw new Error("a hiring call has no pick: the entries are the whole call");
263412
+ const call3 = legCall(input.call, input.leg);
263413
+ if (call3.mode === "hire") throw new Error("a hiring call has no pick: the entries are the whole call");
263404
263414
  const which = input.leg === "prize" ? "the pick" : "a runner-up";
263405
263415
  return {
263406
263416
  v: 2,
263407
- task: taskFor(call2.title, input.leg),
263417
+ task: taskFor(call3.title, input.leg),
263408
263418
  deliverable: { type: "text", prompt: "Quote the number of your entry, nothing else" },
263409
- campaign: callTag(call2.slug),
263419
+ campaign: callTag(call3.slug),
263410
263420
  ...input.access ? { access: input.access } : {},
263411
- call: call2,
263412
- criteria: [{ id: "picked", kind: "attest", text: `The poster chose this entry as ${which} of call ${call2.slug}` }],
263421
+ call: call3,
263422
+ criteria: [{ id: "picked", kind: "attest", text: `The poster chose this entry as ${which} of call ${call3.slug}` }],
263413
263423
  judge: { kind: "poster" }
263414
263424
  };
263415
263425
  }
@@ -263421,8 +263431,8 @@ function callDates(openDays, now3 = Date.now(), mode) {
263421
263431
  }
263422
263432
  return { closes: new Date(closes).toISOString(), drop: new Date(closes + DAY_MS2).toISOString(), pick: new Date(closes + 4 * DAY_MS2).toISOString() };
263423
263433
  }
263424
- function legDays(call2, leg, now3 = Date.now()) {
263425
- const until = leg === "entries" ? Date.parse(call2.closes) : Date.parse(call2.pick) + 7 * DAY_MS2;
263434
+ function legDays(call3, leg, now3 = Date.now()) {
263435
+ const until = leg === "entries" ? Date.parse(call3.closes) : Date.parse(call3.pick) + 7 * DAY_MS2;
263426
263436
  return Math.max(1, Math.ceil((until - now3) / DAY_MS2));
263427
263437
  }
263428
263438
  var ENTRY_MIN_CHARS, REVIEW_LINES, REVIEW_DELIVERABLE_PROMPT, DAY_MS2, legsOf, pickQuota;
@@ -263442,7 +263452,7 @@ var init_call = __esm({
263442
263452
  ];
263443
263453
  REVIEW_DELIVERABLE_PROMPT = "A review report: what you tested, your steps per scenario, each finding with its evidence, how to reproduce it and its severity, what to change, and the limitations";
263444
263454
  DAY_MS2 = 24 * 3600 * 1e3;
263445
- legsOf = (call2) => call2.mode === "hire" ? ["entries"] : ["prize", ...call2.money.runnersN > 0 ? ["runnersUp"] : [], "entries"];
263455
+ legsOf = (call3) => call3.mode === "hire" ? ["entries"] : ["prize", ...call3.money.runnersN > 0 ? ["runnersUp"] : [], "entries"];
263446
263456
  pickQuota = (winners) => winners + 2;
263447
263457
  }
263448
263458
  });
@@ -263711,12 +263721,12 @@ __export(callRead_exports, {
263711
263721
  sharedPay: () => sharedPay,
263712
263722
  stageWords: () => stageWords
263713
263723
  });
263714
- function stageWords(call2, now3 = Date.now()) {
263715
- if (now3 < Date.parse(call2.closes)) return `open until ${day(call2.closes)}`;
263716
- if (call2.mode === "hire") return `closed ${day(call2.closes)}; every entry that passed is paid as it is judged`;
263717
- if (now3 < Date.parse(call2.drop)) return `closed ${day(call2.closes)}; the shortlist shows ${day(call2.drop)}`;
263718
- if (now3 < Date.parse(call2.pick)) return `closed; the shortlist is out; the pick by ${day(call2.pick)}`;
263719
- return `closed; the pick was due ${day(call2.pick)}`;
263724
+ function stageWords(call3, now3 = Date.now()) {
263725
+ if (now3 < Date.parse(call3.closes)) return `open until ${day(call3.closes)}`;
263726
+ if (call3.mode === "hire") return `closed ${day(call3.closes)}; every entry that passed is paid as it is judged`;
263727
+ if (now3 < Date.parse(call3.drop)) return `closed ${day(call3.closes)}; the shortlist shows ${day(call3.drop)}`;
263728
+ if (now3 < Date.parse(call3.pick)) return `closed; the shortlist is out; the pick by ${day(call3.pick)}`;
263729
+ return `closed; the pick was due ${day(call3.pick)}`;
263720
263730
  }
263721
263731
  function sharedPay(quote, share) {
263722
263732
  const leg = grossFor(Math.round(quote * 1e6), share);
@@ -263749,35 +263759,36 @@ ${block2.prompt}`;
263749
263759
  }
263750
263760
  function callReadout(terms, ctx) {
263751
263761
  const amount3 = (value, symbol2) => dollarsOfValue(value, symbol2, ctx.network ?? "mainnet");
263752
- const call2 = terms.call;
263753
- const m = call2.money;
263754
- const hire = call2.mode === "hire";
263762
+ const call3 = terms.call;
263763
+ const m = call3.money;
263764
+ const hire = call3.mode === "hire";
263755
263765
  const lines2 = terms.criteria.filter((one) => one.kind === "judge").map((one) => one.text);
263756
263766
  const n = countWords(lines2.length || 5);
263757
- const entriesId = call2.leg === "entries" ? ctx.id : call2.legs?.entries;
263767
+ const entriesId = call3.leg === "entries" ? ctx.id : call3.legs?.entries;
263758
263768
  const money2 = hire ? [`every entry that passes all ${n} lines is paid ${amount3(m.entryEach, ctx.symbol)}, up to ${m.entryUpTo} ${m.entryUpTo === 1 ? "entry" : "entries"}; there is no pick`] : [
263759
263769
  `the pick gets ${amount3(m.prize, ctx.symbol)}`,
263760
263770
  m.runnersN > 0 ? `${m.runnersN} runner${m.runnersN === 1 ? "-up gets" : "s-up get"} ${amount3(m.runnersEach, ctx.symbol)} each` : "",
263761
263771
  `every entry that passes all ${n} lines is paid ${amount3(m.entryEach, ctx.symbol)}, up to ${m.entryUpTo}`
263762
263772
  ].filter(Boolean);
263763
263773
  const who = terms.access === "invite" ? "By invitation: only the people the poster put on the list can enter. If you were sent a link, pass it as submit_work's `invite`; if your address or page was named, nothing more is needed." : terms.access === "apply" ? "By application: apply_to_call first, with a short note; when the poster says yes, submit_work is admitted." : "Open to anyone.";
263764
- const review = call2.kind === "review";
263765
- const shared = call2.share ? sharedPay(m.entryEach, call2.share) : null;
263766
- const shareLine2 = shared && call2.share ? `each ${review ? "pro" : hire ? "hired person" : "entry paid"} receives ${amount3(shared.receives, ctx.symbol)} (the leg is ${amount3(shared.leg, ctx.symbol)}; the network keeps ${amount3(shared.keeps, ctx.symbol)}: ${shareWords(call2.share, "as posted")})${hire ? "" : "; the pick's and the runners-up's legs carry the same share on top of theirs"}` : "";
263767
- const proMoney = review && call2.share && hire ? `Money: ${feeLine({ split: call2.share, net: m.entryEach, symbol: ctx.symbol, network: ctx.network ?? "mainnet" })} Up to ${m.entryUpTo} ${m.entryUpTo === 1 ? "report is" : "reports are"} paid, each one that passes all ${n} lines; there is no pick. Held on the ask's own account before anyone enters.` : null;
263774
+ const review = call3.kind === "review";
263775
+ const shared = call3.share ? sharedPay(m.entryEach, call3.share) : null;
263776
+ const shareLine2 = shared && call3.share ? `each ${review ? "pro" : hire ? "hired person" : "entry paid"} receives ${amount3(shared.receives, ctx.symbol)} (the leg is ${amount3(shared.leg, ctx.symbol)}; the network keeps ${amount3(shared.keeps, ctx.symbol)}: ${shareWords(call3.share, "as posted")})${hire ? "" : "; the pick's and the runners-up's legs carry the same share on top of theirs"}` : "";
263777
+ const proMoney = review && call3.share && hire ? `Money: ${feeLine({ split: call3.share, net: m.entryEach, symbol: ctx.symbol, network: ctx.network ?? "mainnet" })} Up to ${m.entryUpTo} ${m.entryUpTo === 1 ? "report is" : "reports are"} paid, each one that passes all ${n} lines; there is no pick. Held on the ask's own account before anyone enters.` : null;
263768
263778
  const out = [
263769
- `${review ? "Pro ask" : hire ? "Hiring call" : "Open call"} "${call2.slug}" \xB7 posted by ${call2.poster} \xB7 ${stageWords(call2, ctx.now)}`,
263770
- ...review && ctx.site ? [`Its page: ${ctx.site.replace(/\/+$/, "")}/pro/reviews/${ctx.id}`] : [],
263771
- call2.title,
263772
- call2.lede,
263773
- ...review && call2.subject ? [`Reviewing: ${call2.subject.name}${call2.subject.version ? ` ${call2.subject.version}` : ""}${call2.subject.where ? ` \xB7 ${call2.subject.where}` : ""}. Access details, if any, are in your invitation.`] : [],
263774
- ...review && call2.scenarios?.length ? ["Scenarios, each one a step in your report:", ...call2.scenarios.map((one, index) => ` S${index + 1}. ${one}`)] : [],
263779
+ `${review ? "Pro ask" : hire ? "Hiring call" : "Open call"} "${call3.slug}" \xB7 posted by ${call3.poster} \xB7 ${stageWords(call3, ctx.now)}`,
263780
+ /* A pro ask's page is its poster's alone (2026-10-29); an invited pro reads the same ask as their job, under Work. */
263781
+ ...review && ctx.site ? [`Its pages: the poster's ${ctx.site.replace(/\/+$/, "")}/me/pro-asks/${ctx.id}; an invited pro's job ${ctx.site.replace(/\/+$/, "")}/me/work/${ctx.id}`] : [],
263782
+ call3.title,
263783
+ call3.lede,
263784
+ ...review && call3.subject ? [`Reviewing: ${call3.subject.name}${call3.subject.version ? ` ${call3.subject.version}` : ""}${call3.subject.where ? ` \xB7 ${call3.subject.where}` : ""}. Access details, if any, are in your invitation.`] : [],
263785
+ ...review && call3.scenarios?.length ? ["Scenarios, each one a step in your report:", ...call3.scenarios.map((one, index) => ` S${index + 1}. ${one}`)] : [],
263775
263786
  proMoney ?? `Money: ${[...money2, shareLine2].filter(Boolean).join("; ")}. Locked in ${hire ? "the ask's own account" : "each leg's own account"} before anyone enters.`,
263776
263787
  who,
263777
- call2.leg === "entries" ? review ? `Enter: a review report with screenshots, as submit_work's report and files, collectionId "${ctx.id}"${terms.approver ? `; the AI checks it against the requirements, then ${terms.approver} gives final approval to release payment` : "; the AI checks it against the requirements and a passing report is paid"}. One report per account.` : `Enter: one page of text, in your own words: submit_work collectionId "${ctx.id}". One entry per account.` : `The pick's leg: only the entry the poster picked may claim here, with one line naming it. ${entriesId ? `The entries are ask ${entriesId}.` : "The entries are the call's own ask."}`,
263788
+ call3.leg === "entries" ? review ? `Enter: a review report with screenshots, as submit_work's report and files, collectionId "${ctx.id}"${terms.approver ? `; the AI checks it against the requirements, then ${terms.approver} gives final approval to release payment` : "; the AI checks it against the requirements and a passing report is paid"}. One report per account.` : `Enter: one page of text, in your own words: submit_work collectionId "${ctx.id}". One entry per account.` : `The pick's leg: only the entry the poster picked may claim here, with one line naming it. ${entriesId ? `The entries are ask ${entriesId}.` : "The entries are the call's own ask."}`,
263778
263789
  hire ? `Judged: ${n} requirements that every entry must meet. Pass all ${n} and the entry is paid on approval; nobody is picked.` : `Judged: ${n} requirements that every entry must meet. Pass all ${n} and the entry is paid; how clearly it meets each requirement ranks the entries for the pick.`,
263779
263790
  "",
263780
- ...call2.blocks.map(blockText).flatMap((text4) => [text4, ""]),
263791
+ ...call3.blocks.map(blockText).flatMap((text4) => [text4, ""]),
263781
263792
  `The ${n} requirements:`,
263782
263793
  ...lines2.length ? lines2.map((text4, index) => `${index + 1}. ${text4}`) : ["(on the entries ask)"]
263783
263794
  ];
@@ -264274,7 +264285,7 @@ async function postNextLegNow(slug, ctx) {
264274
264285
  tag: tagOf(draft),
264275
264286
  ...draft.fields.cover?.url ? { cover: draft.fields.cover.url } : {},
264276
264287
  /* A review's page is in its world (world.ts); every other call's on Open Call. */
264277
- url: draft.fields.kind === "review" ? `${ctx.site.replace(/\/+$/, "")}/pro/reviews/${slug}` : `${ctx.site.replace(/\/+$/, "")}/opencall/${slug}`,
264288
+ url: draft.fields.kind === "review" ? `${ctx.site.replace(/\/+$/, "")}/me/pro-asks/${slug}` : `${ctx.site.replace(/\/+$/, "")}/opencall/${slug}`,
264278
264289
  ...dates?.closes ? { endsAt: new Date(new Date(dates.pick ?? dates.closes).getTime() + 30 * 24 * 3600 * 1e3) } : {}
264279
264290
  },
264280
264291
  { onMinted: remember2 }
@@ -264362,10 +264373,10 @@ function callServerEnv(site, env) {
264362
264373
  OPENHANDS_MAX_PER_DAY_USD: env.OPENHANDS_MAX_PER_DAY_USD?.trim() || "100"
264363
264374
  };
264364
264375
  }
264365
- function confirms(said3, totalBase, symbol2) {
264366
- const named = /USDC|PAY|IXO/i.exec(said3)?.[0]?.toUpperCase();
264376
+ function confirms(said4, totalBase, symbol2) {
264377
+ const named = /USDC|PAY|IXO/i.exec(said4)?.[0]?.toUpperCase();
264367
264378
  if (symbol2 && named && named !== symbol2.toUpperCase()) return false;
264368
- const figure = said3.replace(/[$,\s]|USDC|PAY|IXO/gi, "");
264379
+ const figure = said4.replace(/[$,\s]|USDC|PAY|IXO/gi, "");
264369
264380
  return /^\d+(\.\d+)?$/.test(figure) && Math.round(Number(figure) * MICRO5) === totalBase;
264370
264381
  }
264371
264382
  var MICRO5, callsDir, fileOf, askInvitesFile, freshDraft, L3, ENTRIES_MAX, INVITES_MAX, INVITE_NOTE_MAX, ADDRESS2, HANDLE_ITEM, isInviteItem, PRO_ASK_INVITE_ONLY, manyLines, overCap, callTwoCoins, SETTLE_MS, chainCheck, InFlightError, PostRefused, feeUnpaid, said2, indexLookupWith, indexLookup, posting, isAskPending, isTxFailed, tagOf, TESTNET_CALL_DEFAULTS, payWords;
@@ -264545,6 +264556,14 @@ function readLinkedinMessage(message, expected, now3 = Date.now(), maxAgeMs = ST
264545
264556
  if (parts.length !== 5 || parts[0] !== "linkedin" || parts[1] !== expected.act || parts[2] !== expected.signer || parts[4] !== expected.digest) return "mismatch";
264546
264557
  return fresh(parts[3], now3, maxAgeMs);
264547
264558
  }
264559
+ async function cashoutWords(act, signer2, body, now3 = Date.now()) {
264560
+ return cashoutMessage(act, signer2, now3, await digestOf(linkedinBody(body)));
264561
+ }
264562
+ function readCashoutMessage(message, expected, now3 = Date.now(), maxAgeMs = STAFF_PROOF_MAX_AGE_MS) {
264563
+ const parts = message.split(":");
264564
+ if (parts.length !== 5 || parts[0] !== "cashout" || parts[1] !== expected.act || parts[2] !== expected.signer || parts[4] !== expected.digest) return "mismatch";
264565
+ return fresh(parts[3], now3, maxAgeMs);
264566
+ }
264548
264567
  async function roomWords(act, signer2, body, now3 = Date.now()) {
264549
264568
  return roomMessage(act, signer2, now3, await digestOf(roomBody(body)));
264550
264569
  }
@@ -264641,8 +264660,8 @@ function readHandsRemoveMessage(message, expected) {
264641
264660
  if (parts.length !== 3 || parts[0] !== "hands-remove" || parts[1] !== expected.address) return "mismatch";
264642
264661
  return Number(parts[2]) === expected.prefAt ? "ok" : "mismatch";
264643
264662
  }
264644
- function fresh(said3, now3, maxAgeMs) {
264645
- const at = Number(said3);
264663
+ function fresh(said4, now3, maxAgeMs) {
264664
+ const at = Number(said4);
264646
264665
  if (!Number.isFinite(at)) return "mismatch";
264647
264666
  return Math.abs(now3 - at) <= maxAgeMs ? "ok" : "stale";
264648
264667
  }
@@ -264662,7 +264681,7 @@ async function digestOf(value) {
264662
264681
  const bytes3 = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonicalJson2(value))));
264663
264682
  return Array.from(bytes3, (byte) => byte.toString(16).padStart(2, "0")).join("");
264664
264683
  }
264665
- var PROOF_MAX_AGE_MS2, INVITE_OPS, INVITE_WRITES, inviteOpBody, inviteOpMessage, applyMessage, invitedMessage, answersMessage, READ_PROOF_MAX_AGE_MS, FUTURE_SKEW_MS, LEGACY_WORDS_UNTIL, callsMessage, noticesMessage, tellMessage, NOTICE_KINDS, handsMessage, vettingMineMessage, vettingQueueMessage, STAFF_PROOF_MAX_AGE_MS, vetRequestBody, vetRequestMessage, vetBody, vetMessage, handsRemoveMessage, handsMineMessage, LINKEDIN_ACTS, linkedinBody, linkedinMessage, ROOM_ACTS, roomBody, roomMessage, ROOM_SEND_MAX_AGE_MS, SPONSOR_ACTS, sponsorBody, sponsorMessage, HANDS_SHARE_ACTS, handsShareMessage;
264684
+ var PROOF_MAX_AGE_MS2, INVITE_OPS, INVITE_WRITES, inviteOpBody, inviteOpMessage, applyMessage, invitedMessage, answersMessage, READ_PROOF_MAX_AGE_MS, FUTURE_SKEW_MS, LEGACY_WORDS_UNTIL, callsMessage, noticesMessage, tellMessage, NOTICE_KINDS, handsMessage, vettingMineMessage, vettingQueueMessage, STAFF_PROOF_MAX_AGE_MS, vetRequestBody, vetRequestMessage, vetBody, vetMessage, handsRemoveMessage, handsMineMessage, LINKEDIN_ACTS, linkedinBody, linkedinMessage, CASHOUT_ACTS, cashoutMessage, ROOM_ACTS, roomBody, roomMessage, ROOM_SEND_MAX_AGE_MS, SPONSOR_ACTS, sponsorBody, sponsorMessage, HANDS_SHARE_ACTS, handsShareMessage;
264666
264685
  var init_inviteMessages = __esm({
264667
264686
  "../../packages/openhands-sdk/src/chain/inviteMessages.ts"() {
264668
264687
  "use strict";
@@ -264697,6 +264716,8 @@ var init_inviteMessages = __esm({
264697
264716
  return rest;
264698
264717
  };
264699
264718
  linkedinMessage = (act, signer2, now3 = Date.now(), digest2 = "") => `linkedin:${act}:${signer2}:${now3}:${digest2}`;
264719
+ CASHOUT_ACTS = ["quote", "draft", "status"];
264720
+ cashoutMessage = (act, signer2, now3 = Date.now(), digest2 = "") => `cashout:${act}:${signer2}:${now3}:${digest2}`;
264700
264721
  ROOM_ACTS = ["mine", "read", "send", "bring", "export"];
264701
264722
  roomBody = (body) => {
264702
264723
  const { address: _address, proof: _proof, ...rest } = body;
@@ -264743,6 +264764,7 @@ var init_inviteAnswer = __esm({
264743
264764
  var inviteProof_exports = {};
264744
264765
  __export(inviteProof_exports, {
264745
264766
  AVAILABILITY: () => AVAILABILITY,
264767
+ CASHOUT_ACTS: () => CASHOUT_ACTS,
264746
264768
  DOES: () => DOES,
264747
264769
  FUTURE_SKEW_MS: () => FUTURE_SKEW_MS,
264748
264770
  HANDLE: () => HANDLE,
@@ -264770,6 +264792,8 @@ __export(inviteProof_exports, {
264770
264792
  applyMessage: () => applyMessage,
264771
264793
  callsMessage: () => callsMessage,
264772
264794
  canonicalJson: () => canonicalJson2,
264795
+ cashoutMessage: () => cashoutMessage,
264796
+ cashoutWords: () => cashoutWords,
264773
264797
  digestOf: () => digestOf,
264774
264798
  fresh: () => fresh,
264775
264799
  handsMessage: () => handsMessage,
@@ -264789,6 +264813,7 @@ __export(inviteProof_exports, {
264789
264813
  readAnswersMessage: () => readAnswersMessage,
264790
264814
  readApplyMessage: () => readApplyMessage,
264791
264815
  readCallsMessage: () => readCallsMessage,
264816
+ readCashoutMessage: () => readCashoutMessage,
264792
264817
  readHandBlock: () => readHandBlock,
264793
264818
  readHandProfile: () => readHandProfile,
264794
264819
  readHandsMessage: () => readHandsMessage,
@@ -265112,6 +265137,7 @@ __export(invites_exports, {
265112
265137
  inviteItemsOf: () => inviteItemsOf,
265113
265138
  linkedinStatus: () => linkedinStatus,
265114
265139
  markNoticesRead: () => markNoticesRead,
265140
+ myCalls: () => myCalls,
265115
265141
  myInvitations: () => myInvitations,
265116
265142
  noticeWords: () => noticeWords,
265117
265143
  pageWords: () => pageWords,
@@ -265254,6 +265280,23 @@ async function myInvitations(site, signer2, fetchImpl) {
265254
265280
  }
265255
265281
  return { invited };
265256
265282
  }
265283
+ async function myCalls(site, signer2, fetchImpl) {
265284
+ const calls = [];
265285
+ const person = signer2.principal && signer2.principal !== signer2.address ? signer2.principal : null;
265286
+ for (const onBehalfOf of [null, ...person ? [person] : []]) {
265287
+ const message = callsMessage(signer2.address);
265288
+ const answer = await post(site, "/api/invites/calls", { address: signer2.address, ...onBehalfOf ? { onBehalfOf } : {}, closed: true, proof: { kind: "adr36", message, ...await signWords(signer2.mnemonic, message) } }, fetchImpl);
265289
+ const missed = (why) => ({ calls, missed: `the pro asks of ${onBehalfOf}, the account you act for, could not be read just now (${why})` });
265290
+ if (!answer.ok) {
265291
+ if (!onBehalfOf) return { refused: refusalOf(answer) };
265292
+ return missed(refusalOf(answer));
265293
+ }
265294
+ const rows2 = answer.body.calls ?? [];
265295
+ if (onBehalfOf && rows2.some((one) => one.owner && one.owner !== onBehalfOf)) return missed("the site does not read them for an agent yet");
265296
+ for (const one of rows2) if (!calls.some((seen2) => seen2.collectionId === one.collectionId)) calls.push(one);
265297
+ }
265298
+ return { calls };
265299
+ }
265257
265300
  async function readNotices(site, signer2, options = {}, fetchImpl) {
265258
265301
  const message = noticesMessage(signer2.address);
265259
265302
  const answer = await post(site, "/api/invites/notices", { address: signer2.address, ...signer2.principal ? { onBehalfOf: signer2.principal } : {}, ...options, proof: { kind: "adr36", message, ...await signWords(signer2.mnemonic, message) } }, fetchImpl);
@@ -265270,7 +265313,7 @@ function noticeWords(notices, site) {
265270
265313
  return notices.map((one) => {
265271
265314
  const room = one.kind === "message" ? /\/with\/([^/?#]+)$/.exec(one.href)?.[1] : void 0;
265272
265315
  const next = one.kind === "message" ? `read_messages collectionId "${one.collectionId}"${room ? ` with "${decodeURIComponent(room)}"` : ""}` : one.kind === "application" ? `decide_application "${one.collectionId}"` : one.kind === "link-opened" || one.kind === "invite-accepted" ? `call_invites "${one.collectionId}"` : one.kind === "invite-declined" ? `invite_to_call "${one.collectionId}" (someone else)` : one.kind === "invited" && isReviewTitle(one.title) ? `accept_invitation "${one.collectionId}" or decline_invitation` : one.kind === "declined" ? "" : `read_ask "${one.collectionId}"`;
265273
- const href = isReviewTitle(one.title) ? one.href.replace(/^\/opencall\/(?!i\/)([a-z][a-z0-9-]{2,39})$/, "/pro/reviews/$1") : one.href;
265316
+ const href = sitePath(isReviewTitle(one.title) ? one.href.replace(/^\/opencall\/(?!i\/)([a-z][a-z0-9-]{2,39})$/, one.kind === "invited" ? `/me/work/${one.collectionId}` : "/me/pro-asks/$1") : one.href);
265274
265317
  return ` \xB7 ${one.headline}: ${one.line}${/["”.]$/.test(one.line) ? "" : "."} ${base6}${href}${next ? ` \xB7 ${next}` : ""}`;
265275
265318
  });
265276
265319
  }
@@ -266191,13 +266234,13 @@ function shortTitle(task, max = TITLE_MAX) {
266191
266234
  return `${(space > max / 2 ? cut.slice(0, space) : cut).replace(/[\s,;:.-]+$/, "")}\u2026`;
266192
266235
  }
266193
266236
  function askHead(name8, task) {
266194
- const said3 = placeJoined((task ?? "").trim());
266237
+ const said4 = placeJoined((task ?? "").trim());
266195
266238
  const named = (name8 ?? "").trim();
266196
- if (!said3 || said3 === named) return { title: null, task: null };
266239
+ if (!said4 || said4 === named) return { title: null, task: null };
266197
266240
  const stem = named.replace(/…$/, "").trimEnd();
266198
- const cut = (named.endsWith("\u2026") || named.length >= 140) && said3.startsWith(stem);
266199
- const heading = cut ? shortTitle(said3) : named;
266200
- const rest = /[.?!]$/.test(heading) && said3.startsWith(heading) ? said3.slice(heading.length).trim() : said3;
266241
+ const cut = (named.endsWith("\u2026") || named.length >= 140) && said4.startsWith(stem);
266242
+ const heading = cut ? shortTitle(said4) : named;
266243
+ const rest = /[.?!]$/.test(heading) && said4.startsWith(heading) ? said4.slice(heading.length).trim() : said4;
266201
266244
  return { title: cut ? heading : null, task: rest || null };
266202
266245
  }
266203
266246
  var TITLE_MAX, placeJoined;
@@ -266432,10 +266475,10 @@ function clean5(raw) {
266432
266475
  return text4.length <= MAX_LENGTH ? text4 : `${text4.slice(0, MAX_LENGTH - 1).trimEnd()}\u2026`;
266433
266476
  }
266434
266477
  async function placeName(point, zoom, reach = {}) {
266435
- const call2 = reach.fetch ?? globalThis.fetch;
266478
+ const call3 = reach.fetch ?? globalThis.fetch;
266436
266479
  const url4 = `${ENDPOINT}?lat=${encodeURIComponent(point.lat)}&lon=${encodeURIComponent(point.lon)}&format=jsonv2&zoom=${encodeURIComponent(zoom)}`;
266437
266480
  try {
266438
- const response = await call2(url4, {
266481
+ const response = await call3(url4, {
266439
266482
  headers: { "user-agent": USER_AGENT, accept: "application/json" },
266440
266483
  signal: AbortSignal.timeout(TIMEOUT_MS6)
266441
266484
  });
@@ -266832,6 +266875,129 @@ var init_takeBack = __esm({
266832
266875
  }
266833
266876
  });
266834
266877
 
266878
+ // src/cashout.ts
266879
+ var cashout_exports = {};
266880
+ __export(cashout_exports, {
266881
+ cashOut: () => cashOut,
266882
+ cashOutStatus: () => cashOutStatus
266883
+ });
266884
+ async function call2(deps, path, body) {
266885
+ try {
266886
+ const response = await deps.fetch(`${deps.site.replace(/\/+$/, "")}${path}`, {
266887
+ method: body === void 0 ? "GET" : "POST",
266888
+ headers: { accept: "application/json", ...body === void 0 ? {} : { "content-type": "application/json" } },
266889
+ ...body === void 0 ? {} : { body: JSON.stringify(body) },
266890
+ signal: AbortSignal.timeout(2e4)
266891
+ });
266892
+ return { status: response.status, body: await response.json().catch(() => ({})) ?? {} };
266893
+ } catch {
266894
+ return { status: 0, body: { error: "asks.world did not answer. Try again shortly." } };
266895
+ }
266896
+ }
266897
+ async function signedCall(deps, act, fields) {
266898
+ const full = { ...fields, ...deps.signer.principal ? { onBehalfOf: deps.signer.principal } : {} };
266899
+ const message = await cashoutWords(act, deps.signer.address, full);
266900
+ return call2(deps, `/api/cashout/${act}`, { address: deps.signer.address, ...full, proof: { kind: "adr36", message, ...await signWords(deps.signer.mnemonic, message) } });
266901
+ }
266902
+ async function cashOut(deps, input) {
266903
+ const person = deps.signer.principal ?? deps.signer.address;
266904
+ const [ready, payBase] = await Promise.all([signedCall(deps, "status", {}), deps.payBase(person)]);
266905
+ if (ready.status !== 200) return said3(ready);
266906
+ const kyc = ready.body.kyc;
266907
+ if (!ready.body.linkedin) return "Cash-out needs your LinkedIn connected first. Next: connect_linkedin (about a minute), then cash_out again.";
266908
+ const available = payBase / 1e6;
266909
+ if (available <= 0) return "You have no PAY to cash out yet.";
266910
+ const kycLine = kyc?.status === "verified" ? "" : kyc?.status === "expired" ? `Your identity check has expired. Renew it first: ${deps.site.replace(/\/+$/, "")}/me/identity` : `Cash-out needs an identity check. If you haven't done it yet, do it first: ${deps.site.replace(/\/+$/, "")}/me/identity`;
266911
+ if (kyc?.status === "expired") return kycLine;
266912
+ const country = input.country?.trim().toUpperCase();
266913
+ if (!country || !/^[A-Z]{2}$/.test(country)) return [`You have $${available.toFixed(2)} in PAY to cash out.`, kycLine, 'Which country are you in? (Ask the person; then call cash_out with country, like "NG" or "DE".)'].filter(Boolean).join("\n");
266914
+ const info = await call2(deps, `/api/cashout/info?country=${country}`);
266915
+ if (info.status !== 200) return said3(info);
266916
+ const methods = info.body.methods ?? [];
266917
+ const fee = info.body.fee;
266918
+ if (!methods.length) return `There's no way to cash out in ${country} yet.`;
266919
+ const chosen2 = methods.find((one) => one.method === input.method);
266920
+ if (!chosen2)
266921
+ return [
266922
+ `You have $${available.toFixed(2)} in PAY. Ways to get paid in ${country}:`,
266923
+ ...methods.map((one) => `- ${WAYS[one.method] ?? one.method} (method "${one.method}"): $${one.minUsd} to $${one.maxUsd}`),
266924
+ `Fee: ${fee?.bps ? `${fee.bps / 100}%` : "none"}${fee?.minUsd && Number(fee.minUsd) > 0 ? `, at least $${fee.minUsd}` : ""}.`,
266925
+ kycLine,
266926
+ "(Ask which way and how much; then call cash_out with method and amount_usd.)"
266927
+ ].filter(Boolean).join("\n");
266928
+ const amount3 = input.amount_usd?.trim().replace(/^\$/, "");
266929
+ if (!amount3 || !/^\d+(\.\d{1,2})?$/.test(amount3)) return `How much do you want to cash out? You have $${available.toFixed(2)}; this way takes $${chosen2.minUsd} to $${chosen2.maxUsd}. (Then call cash_out with amount_usd, like "25".)`;
266930
+ if (Number(amount3) > available) return `You have $${available.toFixed(2)} in PAY, less than $${amount3}. Pick a smaller amount.`;
266931
+ if (Number(amount3) < Number(chosen2.minUsd)) return `The smallest you can cash out this way is $${chosen2.minUsd}.`;
266932
+ if (Number(amount3) > Number(chosen2.maxUsd)) return `The largest you can cash out this way is $${chosen2.maxUsd}.`;
266933
+ const to = input.to?.trim();
266934
+ if (chosen2.fields.includes("address") && !(to && BASE_ADDRESS.test(to))) return "Which Base address should receive the USDC? (An 0x\u2026 address on Base; then call cash_out with to.)";
266935
+ const quote = await signedCall(deps, "quote", { method: chosen2.method, country, amountUsd: amount3 });
266936
+ if (quote.status !== 201) return said3(quote);
266937
+ const q = quote.body;
266938
+ const receive = `You'll receive $${q.receive?.amount ?? q.amountUsd}${q.receive?.currency && q.receive.currency !== "USD" ? ` in ${q.receive.currency}` : ""} (fee $${q.feeUsd ?? "0.00"}).`;
266939
+ const named = chosen2.fields.includes("accountHolder") ? NAME_LINE : "";
266940
+ if (!input.confirm) return [`Cash out $${q.amountUsd} by ${WAYS[chosen2.method] ?? chosen2.method}${to ? ` to ${to}` : ""}.`, receive, named, kycLine, "Nothing is sent yet. To go ahead, call cash_out again with the same answers and confirm: true."].filter(Boolean).join("\n");
266941
+ const link5 = new URL(`${deps.site.replace(/\/+$/, "")}/me/cash-out`);
266942
+ link5.searchParams.set("quote", String(q.quoteId));
266943
+ link5.searchParams.set("method", chosen2.method);
266944
+ link5.searchParams.set("amount", amount3);
266945
+ link5.searchParams.set("country", country);
266946
+ if (to) link5.searchParams.set("to", to);
266947
+ return [receive, named, `Open this and confirm with one tap: ${link5.toString()}`, "Your money leaves only when you confirm there. I signed nothing. (Later, cash_out_status with the id that page shows says where it stands.)"].filter(Boolean).join("\n");
266948
+ }
266949
+ async function cashOutStatus(deps, id) {
266950
+ const answer = await signedCall(deps, "status", { id });
266951
+ if (answer.status === 404) return `No cash-out "${id}" for you on this network.`;
266952
+ if (answer.status !== 200) return said3(answer);
266953
+ const v = answer.body;
266954
+ const lapsed = id.startsWith("cd_") && (v.state === "open" || v.state === "signing") && Date.parse(v.expiresAt ?? "") <= Date.now();
266955
+ const money2 = v.receive?.amount ? `$${v.receive.amount}${v.receive.currency && v.receive.currency !== "USD" ? ` ${v.receive.currency}` : ""}` : v.quote?.amountUsd ? `$${v.quote.amountUsd}` : "your cash-out";
266956
+ switch (lapsed ? "expired" : v.state) {
266957
+ case "open":
266958
+ case "signing":
266959
+ return `Not confirmed yet: open the confirm link and tap confirm (${money2}).`;
266960
+ case "sent":
266961
+ return "Confirmed. The payout is starting.";
266962
+ case "expired":
266963
+ case "failed":
266964
+ return "This cash-out expired before it was confirmed. Nothing was taken. Start a new one with cash_out.";
266965
+ case "converting":
266966
+ case "taking":
266967
+ case "paying":
266968
+ return `On its way: ${money2}.`;
266969
+ case "paid":
266970
+ return `Paid: ${money2}.`;
266971
+ case "needs_attention":
266972
+ return `Your payout didn't go through: ${v.reason ?? "the payout failed"}. Check your details or pick another way: ${v.fixUrl ?? ""}
266973
+ ${NAME_LINE}`;
266974
+ case "not_converted":
266975
+ case "cancelled":
266976
+ return "This cash-out didn't go through, and nothing was taken.";
266977
+ case "refunded":
266978
+ return "Your PAY was sent back to you.";
266979
+ default:
266980
+ return `State: ${v.state ?? "unknown"}.`;
266981
+ }
266982
+ }
266983
+ var WAYS, BASE_ADDRESS, NAME_LINE, said3;
266984
+ var init_cashout = __esm({
266985
+ "src/cashout.ts"() {
266986
+ "use strict";
266987
+ init_accountProof();
266988
+ init_inviteProof();
266989
+ WAYS = {
266990
+ usdc_base: "USDC on Base (any country)",
266991
+ stripe_bank: "Bank account, through Stripe",
266992
+ yellowcard_bank: "Bank account, through Yellow Card",
266993
+ yellowcard_momo: "Mobile money, through Yellow Card"
266994
+ };
266995
+ BASE_ADDRESS = /^0x[0-9a-fA-F]{40}$/;
266996
+ NAME_LINE = "The payout account name must match the name on your ID.";
266997
+ said3 = (answer) => answer.status === 503 && answer.body.code === "not-open" ? "Cash-out isn't open on this network yet." : String(answer.body.error ?? `Cash-out refused this (${answer.status}).`);
266998
+ }
266999
+ });
267000
+
266835
267001
  // src/pairing.ts
266836
267002
  var pairing_exports = {};
266837
267003
  __export(pairing_exports, {
@@ -266876,7 +267042,7 @@ var init_pairing = __esm({
266876
267042
  CODE = /^[a-f0-9]{16}$/;
266877
267043
  memoFor = (code10) => `openhands-connect:${code10}`;
266878
267044
  connectLinkWithCode = (site, agent, code10) => `${site}/connect?agent=${encodeURIComponent(agent)}&code=${code10}`;
266879
- pairingSite = (site, pairing) => pairing.reviews ? `${site.replace(/\/+$/, "")}/pro` : site;
267045
+ pairingSite = (site, _pairing) => site;
266880
267046
  }
266881
267047
  });
266882
267048
 
@@ -266951,6 +267117,8 @@ function roomRows(counts) {
266951
267117
  switch (room.key) {
266952
267118
  case "page":
266953
267119
  return { ...room, figure: null, after: null, ...counts.page === "listed" ? { chip: "Listed" } : counts.page === "private" ? { chip: "Private" } : counts.page === "verify" ? { verify: true } : {} };
267120
+ case "proAsks":
267121
+ return { ...room, ...counted(counts.proAsks ?? null, null) };
266954
267122
  case "work":
266955
267123
  return { ...room, ...counted(counts.work, "waiting") };
266956
267124
  case "messages":
@@ -266972,6 +267140,7 @@ var init_meRooms = __esm({
266972
267140
  "use strict";
266973
267141
  ROOMS = [
266974
267142
  { key: "page", word: "Your page", href: "/me/page" },
267143
+ { key: "proAsks", word: "Pro asks", href: "/me/pro-asks" },
266975
267144
  { key: "work", word: "Work", href: "/me/work" },
266976
267145
  { key: "messages", word: "Messages", href: "/me/messages" },
266977
267146
  { key: "inbox", word: "Inbox", href: "/me/check" },
@@ -266984,6 +267153,53 @@ var init_meRooms = __esm({
266984
267153
  }
266985
267154
  });
266986
267155
 
267156
+ // src/proAsks.ts
267157
+ var proAsks_exports = {};
267158
+ __export(proAsks_exports, {
267159
+ approvePreview: () => approvePreview,
267160
+ handOver: () => handOver,
267161
+ proAskLines: () => proAskLines,
267162
+ proAsksOf: () => proAsksOf,
267163
+ reportPage: () => reportPage,
267164
+ shortDate: () => shortDate
267165
+ });
267166
+ function proAskLines(site, calls, options = {}) {
267167
+ const now3 = options.now ?? Date.now();
267168
+ const base6 = site.replace(/\/+$/, "");
267169
+ return proAsksOf(calls).flatMap((one) => {
267170
+ const open = isOpen2(one, now3);
267171
+ const parts = [open ? "Open" : "Closed", `${one.count} of ${one.quota} reports`];
267172
+ const closes = open ? shortDate(one.end_date) : "";
267173
+ if (closes) parts.push(`closes ${closes}`);
267174
+ const held = options.held?.get(one.collectionId);
267175
+ if (held) parts.push(`holds ${held}`);
267176
+ const toApprove = options.waiting?.filter((item) => item.collectionId === one.collectionId).length ?? 0;
267177
+ if (toApprove) parts.push(`${toApprove} ${toApprove === 1 ? "report" : "reports"} to approve`);
267178
+ return [`#${one.collectionId} ${bare(one.title)} \xB7 ${parts.join(" \xB7 ")}`, ` ${base6}/me/pro-asks/${one.collectionId}`];
267179
+ });
267180
+ }
267181
+ function approvePreview(site, input) {
267182
+ const page = reportPage(site, input.collectionId, input.claimId);
267183
+ const what = `Approving report ${input.claimId} on pro ask #${input.collectionId} pays ${input.pro}${input.pays ? ` ${input.pays}` : ""} from what the ask holds. Approval is final.`;
267184
+ return input.canSign ? [what, `The report: ${page}`, "", "To approve, call approve_report again with confirm: true."].join("\n") : [what, handOver(site, input), "Nothing was sent."].join("\n");
267185
+ }
267186
+ var bare, shortDate, isOpen2, proAsksOf, reportPage, handOver;
267187
+ var init_proAsks = __esm({
267188
+ "src/proAsks.ts"() {
267189
+ "use strict";
267190
+ init_world();
267191
+ bare = (title) => (title ?? "").replace(/^Expert review:\s*/, "") || "A pro ask";
267192
+ shortDate = (iso) => {
267193
+ const at = iso ? new Date(iso) : null;
267194
+ return at && !Number.isNaN(at.getTime()) ? at.toLocaleDateString("en-GB", { day: "numeric", month: "short", timeZone: "UTC" }) : "";
267195
+ };
267196
+ isOpen2 = (one, now3) => one.state === 0 && (!one.end_date || Date.parse(one.end_date) > now3);
267197
+ proAsksOf = (calls) => calls.filter((one) => isReviewTitle(one.title)).sort((a, b) => Number(b.collectionId) - Number(a.collectionId));
267198
+ reportPage = (site, collectionId, claimId) => `${site.replace(/\/+$/, "")}/pro/reviews/${collectionId}/report/${encodeURIComponent(claimId)}`;
267199
+ handOver = (site, input) => `Only ${input.approver} can give this OK, signed in as themselves: the Approve button on the report's page, ${reportPage(site, input.collectionId, input.claimId)}#decide. This key acts for them but cannot sign their OK at the verifier.`;
267200
+ }
267201
+ });
267202
+
266987
267203
  // src/verdictSource.ts
266988
267204
  var verdictSource_exports = {};
266989
267205
  __export(verdictSource_exports, {
@@ -292144,7 +292360,7 @@ import { randomBytes as randomBytes7 } from "node:crypto";
292144
292360
  // package.json
292145
292361
  var package_default = {
292146
292362
  name: "@ixo/asks-mcp",
292147
- version: "2.0.0-dev.1",
292363
+ version: "2.0.0-dev.3",
292148
292364
  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.",
292149
292365
  license: "Apache-2.0",
292150
292366
  repository: {
@@ -292366,6 +292582,20 @@ var TOOLS = {
292366
292582
  /* A second sweep finds nothing to send: the first one emptied the key. */
292367
292583
  annotations: { ...acts, idempotentHint: true }
292368
292584
  },
292585
+ cash_out: {
292586
+ title: "Cash out your PAY",
292587
+ description: `Turn the PAY the person earned into money: USDC on Base, or a bank account where offered. One step per call: it reads their PAY, their LinkedIn and identity check, then asks the country, the way to get paid, the amount and (for USDC) the Base address, and shows the quote in plain words ("You'll receive $X (fee $0)"). With confirm: true it gives ONE link: the person opens it and confirms with one tap; that page checks their identity and they sign there. Limits and fees come from IXO's cash-out service, never from here. No LinkedIn: say connect_linkedin first. Signs no money and holds no key of theirs.`,
292588
+ spends: false,
292589
+ hosted: false,
292590
+ annotations: acts
292591
+ },
292592
+ cash_out_status: {
292593
+ title: "Where a cash-out stands",
292594
+ description: "Given a cash-out's id (cd_\u2026 or wd_\u2026, from the confirm page), says where it stands in plain words: waiting for the tap, on its way, paid, or that it didn't go through and where to fix it. Spends nothing.",
292595
+ spends: false,
292596
+ hosted: false,
292597
+ annotations: reads
292598
+ },
292369
292599
  my_status: {
292370
292600
  title: "This participant's standing",
292371
292601
  description: "Address, the account area as seven lines (Your page, Work waiting, Messages unread, Inbox, Money, Agents, Settings, as asks.world/me draws them), what is available and what is on your asks, answers sent, and rewards still owed.",
@@ -292476,6 +292706,20 @@ var TOOLS = {
292476
292706
  hosted: false,
292477
292707
  annotations: { ...reads, readOnlyHint: true }
292478
292708
  },
292709
+ my_pro_asks: {
292710
+ title: "List the pro asks the person posted",
292711
+ description: `The pro asks this key posted, and those of the person it acts for, newest first, one line each as the site's Pro asks room says them: Open or Closed, how many reports of how many, when it closes, what it holds, and what waits for them ("1 report to approve"), with its page, which only they can open. The next step on each is a tool: invite_to_call, collect_answer (reads its reports), approve_report, close_ask. Spends nothing.`,
292712
+ spends: false,
292713
+ hosted: false,
292714
+ annotations: { ...reads, readOnlyHint: true }
292715
+ },
292716
+ approve_report: {
292717
+ title: "Approve a report on a pro ask (spends money)",
292718
+ description: "Give the final OK on one report a pro sent to a pro ask: the verifier records it and the pro is paid from what the ask holds. Approval is final. Call without confirm first: it says the report, who sent it, what approving pays and whose OK it is; then again with confirm: true, which approves when this key is the one the ask names to give the OK. When the OK is the person's own (a pro ask posted for them), it hands them the report's Approve button on the site instead, and sends nothing.",
292719
+ spends: true,
292720
+ hosted: false,
292721
+ annotations: acts
292722
+ },
292479
292723
  accept_invitation: {
292480
292724
  title: "Accept an invitation to a pro ask",
292481
292725
  description: "Accept an invitation to a pro ask: a link or the ask's number. As the account you act for when connected, else as this key. The builder hears you accepted, and your room with them opens with their note first; a link becomes yours, so nobody else can use it. Someone who is not a verified pro is refused, and the link stays open. Previews; `confirm: true` accepts, once the person says yes. Spends nothing.",
@@ -292949,17 +293193,17 @@ function measureOf(reason) {
292949
293193
  function reasonText(reason) {
292950
293194
  const rest = reason.detail.startsWith(`${reason.label}: `) ? reason.detail.slice(reason.label.length + 2) : reason.detail;
292951
293195
  const measure = measureOf(reason);
292952
- const said3 = rest === reason.label || rest === RESULT_WORD[reason.result] || rest === "Did not pass" ? "" : rest;
292953
- const sayMeasured = reason.value !== void 0 && said3.startsWith(num2(reason.value, reason.unit));
292954
- return [sayMeasured ? "" : measure, said3].filter(Boolean).join(". ");
293196
+ const said4 = rest === reason.label || rest === RESULT_WORD[reason.result] || rest === "Did not pass" ? "" : rest;
293197
+ const sayMeasured = reason.value !== void 0 && said4.startsWith(num2(reason.value, reason.unit));
293198
+ return [sayMeasured ? "" : measure, said4].filter(Boolean).join(". ");
292955
293199
  }
292956
293200
  var evidenceLine = (why) => why.evidenceGrade ? `Time/place: ${why.evidenceGrade}` : null;
292957
293201
  function whyLines(why, indent3 = "") {
292958
293202
  if (!why) return [`${indent3}${WHY_UNREADABLE}.`];
292959
293203
  const lines2 = [`${indent3}${why.summary}`];
292960
293204
  for (const reason of why.reasons) {
292961
- const said3 = reasonText(reason);
292962
- lines2.push(`${indent3} ${RESULT_WORD[reason.result]}: ${reason.label}${said3 ? ` \u2014 ${said3}` : ""}`);
293205
+ const said4 = reasonText(reason);
293206
+ lines2.push(`${indent3} ${RESULT_WORD[reason.result]}: ${reason.label}${said4 ? ` \u2014 ${said4}` : ""}`);
292963
293207
  }
292964
293208
  const evidence = evidenceLine(why);
292965
293209
  if (evidence) lines2.push(`${indent3}${evidence}`);
@@ -293098,8 +293342,8 @@ function whyFromReceipt(receipt, rubric) {
293098
293342
  const push = (r) => {
293099
293343
  const clean6 = { ...r, label: scrub(r.label, 200), detail: scrub(r.detail) };
293100
293344
  const key = `${clean6.result}|${clean6.label}`;
293101
- const bare = clean6.detail === "Passed" || clean6.detail === "Did not pass";
293102
- if (seen2.has(`${key}|${clean6.detail}`) || bare && seen2.has(key)) return;
293345
+ const bare2 = clean6.detail === "Passed" || clean6.detail === "Did not pass";
293346
+ if (seen2.has(`${key}|${clean6.detail}`) || bare2 && seen2.has(key)) return;
293103
293347
  seen2.add(key).add(`${key}|${clean6.detail}`);
293104
293348
  reasons.push(clean6);
293105
293349
  };
@@ -294368,10 +294612,10 @@ To go ahead, call again with confirm: "${token}".`;
294368
294612
  return chargeDay(args.bucket, args.total);
294369
294613
  }
294370
294614
  const withNotes = (guard, notes) => {
294371
- const said3 = notes.filter((note) => Boolean(note));
294372
- return guard.startsWith("Refused") || said3.length === 0 ? guard : `${guard}
294615
+ const said4 = notes.filter((note) => Boolean(note));
294616
+ return guard.startsWith("Refused") || said4.length === 0 ? guard : `${guard}
294373
294617
 
294374
- ${said3.join("\n")}`;
294618
+ ${said4.join("\n")}`;
294375
294619
  };
294376
294620
  const principal2 = async () => actingFor2(await address2());
294377
294621
  const unchosen = async () => {
@@ -294540,18 +294784,18 @@ Each is its own ask and pays on its own. Read one with read_ask before deciding.
294540
294784
  calls.set(tag, { slug, entries: entries2, shared });
294541
294785
  })
294542
294786
  );
294543
- const callLine = (row, call2) => {
294787
+ const callLine = (row, call3) => {
294544
294788
  const summary = row.campaignSummary;
294545
- const review = isReviewTitle(call2.entries?.title);
294546
- const title = call2.entries?.title.replace(/^(Open call|Expert review): /, "") ?? null;
294789
+ const review = isReviewTitle(call3.entries?.title);
294790
+ const title = call3.entries?.title.replace(/^(Open call|Expert review): /, "") ?? null;
294547
294791
  if (title) taint2(title);
294548
294792
  const facts = row.callSummary;
294549
- const shares = call2.shared;
294550
- const entryPays = shares && facts?.entryEach !== void 0 && call2.entries?.pays ? `${faceOf2({ value: facts.entryEach, symbol: call2.entries.pays.symbol }, SANDBOX)?.text} (the network's share is on top of it)` : call2.entries?.pays ? `${faceOf2(call2.entries.pays, SANDBOX)?.text}${shares ? ", less the network's share" : ""}` : void 0;
294793
+ const shares = call3.shared;
294794
+ const entryPays = shares && facts?.entryEach !== void 0 && call3.entries?.pays ? `${faceOf2({ value: facts.entryEach, symbol: call3.entries.pays.symbol }, SANDBOX)?.text} (the network's share is on top of it)` : call3.entries?.pays ? `${faceOf2(call3.entries.pays, SANDBOX)?.text}${shares ? ", less the network's share" : ""}` : void 0;
294551
294795
  return [
294552
- `${review ? "Expert review" : "Open call"} "${call2.slug}" \xB7 ${summary.open} of ${summary.places} legs open${entryPays ? ` \xB7 every ${review ? "report" : "entry"} that meets the bar is paid ${entryPays}` : ""} \xB7 needs-a-human`,
294796
+ `${review ? "Expert review" : "Open call"} "${call3.slug}" \xB7 ${summary.open} of ${summary.places} legs open${entryPays ? ` \xB7 every ${review ? "report" : "entry"} that meets the bar is paid ${entryPays}` : ""} \xB7 needs-a-human`,
294553
294797
  title ? asData("ask-title", title) : "",
294554
- `${review ? "A specialist's report on the review's scenarios, assessed against its requirements. A report that meets them is paid, after the builder's final approval when they give one." : "A written entry assessed against five requirements. Entries that meet all five are paid. For competitions, the poster also chooses a prize winner."} ${call2.entries ? `Read it with read_ask "${call2.entries.id}"; the page is` : "Read its legs on the page:"} ${review ? `${EXPERT_SITE}/pro/reviews/${call2.entries?.id ?? call2.slug}` : `${SITE}/opencall/${call2.slug}`}`
294798
+ `${review ? "A specialist's report on the review's scenarios, assessed against its requirements. A report that meets them is paid, after the builder's final approval when they give one." : "A written entry assessed against five requirements. Entries that meet all five are paid. For competitions, the poster also chooses a prize winner."} ${call3.entries ? `Read it with read_ask "${call3.entries.id}"; the page is` : "Read its legs on the page:"} ${review ? `${EXPERT_SITE}/me/pro-asks/${call3.entries?.id ?? call3.slug}` : `${SITE}/opencall/${call3.slug}`}`
294555
294799
  ].filter(Boolean).join("\n");
294556
294800
  };
294557
294801
  const lines2 = board.rows.filter(within2).map((row) => {
@@ -294569,8 +294813,8 @@ Each is its own ask and pays on its own. Read one with read_ask before deciding.
294569
294813
  }
294570
294814
  if ((row.card === "campaign" || row.card === "call") && row.campaignSummary) {
294571
294815
  const summary = row.campaignSummary;
294572
- const call2 = calls.get(summary.tag);
294573
- if (call2) return callLine(row, call2);
294816
+ const call3 = calls.get(summary.tag);
294817
+ if (call3) return callLine(row, call3);
294574
294818
  const low = summary.low ? faceOf2(summary.low, SANDBOX)?.text : void 0;
294575
294819
  const high = summary.high ? faceOf2(summary.high, SANDBOX)?.text : void 0;
294576
294820
  const range = summary.pool || !low ? "paid from pools" : high && high !== low ? `${low} to ${high} a place` : `${low} a place`;
@@ -294821,13 +295065,13 @@ You cannot complete it, and trying would spend the gate's network fee to be reje
294821
295065
  });
294822
295066
  if (!granted.ok) {
294823
295067
  const body = await granted.text();
294824
- let said3 = body.slice(0, 200);
295068
+ let said4 = body.slice(0, 200);
294825
295069
  try {
294826
295070
  const parsed = JSON.parse(body);
294827
- if (typeof parsed.error === "string" && parsed.error) said3 = parsed.error.replace(/\.?$/, ".");
295071
+ if (typeof parsed.error === "string" && parsed.error) said4 = parsed.error.replace(/\.?$/, ".");
294828
295072
  } catch {
294829
295073
  }
294830
- return `The gate refused: ${said3}`;
295074
+ return `The gate refused: ${said4}`;
294831
295075
  }
294832
295076
  return null;
294833
295077
  };
@@ -294872,9 +295116,9 @@ You cannot complete it, and trying would spend the gate's network fee to be reje
294872
295116
  ...lane ? { private: true, fit: lane.fit, upload: lane.store.upload, fetchBack: lane.store.fetchBack, publish: lane.store.publish } : {}
294873
295117
  };
294874
295118
  const who = { submitter, ...acting ? { delegate: actor.address } : {}, ...alias ? { alias } : {} };
294875
- const said3 = report ? await sendReport({ collectionId, report, paths: files ?? [], requirement, ...uses_memory ? { usesMemory: true } : {}, ...who }, world) : await sendFields({ fields: expertAsk.check.fields, values: fields, collectionId, ...who }, world);
294876
- if (said3.startsWith("Answered")) nudge("scan", collectionId, expertAsk?.checker ?? (await Promise.resolve().then(() => (init_call2(), call_exports2))).nudgeAtFor(NETWORK2, judgeAddress));
294877
- return text4(withAccepted(expertAsk && said3.startsWith("Answered") ? said3.replace(/^(Answered #\d+ as \S+)\./, `$1, for ${expertAsk.checker.name} to check.`) : said3));
295119
+ const said4 = report ? await sendReport({ collectionId, report, paths: files ?? [], requirement, ...uses_memory ? { usesMemory: true } : {}, ...who }, world) : await sendFields({ fields: expertAsk.check.fields, values: fields, collectionId, ...who }, world);
295120
+ if (said4.startsWith("Answered")) nudge("scan", collectionId, expertAsk?.checker ?? (await Promise.resolve().then(() => (init_call2(), call_exports2))).nudgeAtFor(NETWORK2, judgeAddress));
295121
+ return text4(withAccepted(expertAsk && said4.startsWith("Answered") ? said4.replace(/^(Answered #\d+ as \S+)\./, `$1, for ${expertAsk.checker.name} to check.`) : said4));
294878
295122
  }
294879
295123
  const refusedToPrepare = await prepare2();
294880
295124
  if (refusedToPrepare) return text4(withAccepted(refusedToPrepare));
@@ -295278,18 +295522,18 @@ ${SITE}/t/${earlier.id}`);
295278
295522
  const callPerCheck = async (checker = CHECKER) => (await Promise.resolve().then(() => (init_reviewBilling(), reviewBilling_exports))).deploymentBillsPerCheck(checker).catch(() => false);
295279
295523
  const callChecker2 = async (review) => (await Promise.resolve().then(() => (init_call2(), call_exports2))).callChecker(NETWORK2, review, CHECKER);
295280
295524
  const callSplit = async () => (await Promise.resolve().then(() => (init_query43(), query_exports43))).feeSplitOrNull();
295281
- async function sharedPays(leg, posted, bare = false) {
295525
+ async function sharedPays(leg, posted, bare2 = false) {
295282
295526
  if (leg?.is_oracle_payment !== true || !leg.amount?.[0]) return null;
295283
295527
  const { coinDisplay: coinDisplay2, faceOf: faceOf2 } = await Promise.resolve().then(() => (init_format(), format_exports));
295284
295528
  const { netOf: netOf2 } = await Promise.resolve().then(() => (init_share(), share_exports));
295285
295529
  const { shareWords: shareWords2 } = await Promise.resolve().then(() => (init_callRead(), callRead_exports));
295286
295530
  const { denom, amount: amount3 } = leg.amount[0];
295287
- const said3 = (base6) => faceOf2(coinDisplay2([{ denom, amount: String(base6) }]), SANDBOX)?.text ?? "see the record";
295531
+ const said4 = (base6) => faceOf2(coinDisplay2([{ denom, amount: String(base6) }]), SANDBOX)?.text ?? "see the record";
295288
295532
  const split3 = posted ?? await callSplit();
295289
- if (!split3) return `${said3(Number(amount3))} less the network's share (the fee split could not be read just now)`;
295533
+ if (!split3) return `${said4(Number(amount3))} less the network's share (the fee split could not be read just now)`;
295290
295534
  const receives = netOf2(Number(amount3), split3);
295291
- if (bare) return said3(receives);
295292
- return `${said3(receives)} (the leg is ${said3(Number(amount3))}; the network keeps ${said3(Number(amount3) - receives)}: ${shareWords2(split3, posted ? "as posted" : "today")})`;
295535
+ if (bare2) return said4(receives);
295536
+ return `${said4(receives)} (the leg is ${said4(Number(amount3))}; the network keeps ${said4(Number(amount3) - receives)}: ${shareWords2(split3, posted ? "as posted" : "today")})`;
295293
295537
  }
295294
295538
  const callLocks = (rewardBase, feeBase, symbol2 = ASK_SYMBOL) => `${pays(rewardBase, symbol2)}${feeBase > 0 ? ` and ${feeWords(feeBase)} for reviews` : ""}`;
295295
295539
  function escrowTotal(pay, spots, legBase, symbol2 = ASK_SYMBOL, sameCoin = true, feeSymbol = FEE_SYMBOL) {
@@ -295897,11 +296141,42 @@ Left on this key: ${skipped.length === 1 ? "a coin" : `${skipped.length} coins`}
295897
296141
  ],
295898
296142
  "earnings home"
295899
296143
  );
295900
- const said3 = coinsSaid(moving);
295901
- return text4(`Sent ${said3} to ${home}.
296144
+ const said4 = coinsSaid(moving);
296145
+ return text4(`Sent ${said4} to ${home}.
295902
296146
  tx ${result.transactionHash}${leftWords}`);
295903
296147
  }
295904
296148
  );
296149
+ const cashoutDeps = async () => {
296150
+ const acting = await principal2();
296151
+ const key = await loadKey2();
296152
+ return { site: SITE, signer: { address: await address2(), mnemonic: key.mnemonic, principal: acting?.principal ?? null }, fetch: fetch2 };
296153
+ };
296154
+ if (offered("cash_out")) server2.registerTool(
296155
+ "cash_out",
296156
+ {
296157
+ ...meta3("cash_out"),
296158
+ inputSchema: {
296159
+ country: external_exports.string().max(2).optional().describe("Where the person lives: two letters, like NG or DE."),
296160
+ method: external_exports.string().max(40).optional().describe("The way to get paid, as cash_out listed it (like usdc_base)."),
296161
+ amount_usd: external_exports.string().max(12).optional().describe('How much, in dollars, like "25" or "25.50".'),
296162
+ to: external_exports.string().max(64).optional().describe("USDC on Base only: the 0x\u2026 address that receives it."),
296163
+ confirm: external_exports.boolean().optional().describe("true, after the person said yes to the quote: gives the one link to confirm.")
296164
+ }
296165
+ },
296166
+ async (args) => {
296167
+ const { cashOut: cashOut2 } = await Promise.resolve().then(() => (init_cashout(), cashout_exports));
296168
+ const participant = await Promise.resolve().then(() => (init_src5(), src_exports4));
296169
+ return text4(await cashOut2({ ...await cashoutDeps(), payBase: async (who) => Number((await participant.balancesOf(who)).upay ?? 0) }, args));
296170
+ }
296171
+ );
296172
+ if (offered("cash_out_status")) server2.registerTool(
296173
+ "cash_out_status",
296174
+ { ...meta3("cash_out_status"), inputSchema: { id: external_exports.string().regex(/^(cd|wd)_[a-z2-7]{24}$/).describe("The cash-out's id, cd_\u2026 or wd_\u2026.") } },
296175
+ async ({ id }) => {
296176
+ const { cashOutStatus: cashOutStatus2 } = await Promise.resolve().then(() => (init_cashout(), cashout_exports));
296177
+ return text4(await cashOutStatus2(await cashoutDeps(), id));
296178
+ }
296179
+ );
295905
296180
  if (offered("set_payout_settings")) {
295906
296181
  server2.registerTool("set_payout_settings", { ...meta3("set_payout_settings"), inputSchema: settingsInput }, async (args) => {
295907
296182
  const { readOrgPayouts: readOrgPayouts2, facilitatorHealth: facilitatorHealth2, oracleResolves: oracleResolves2 } = await Promise.resolve().then(() => (init_orgPayouts(), orgPayouts_exports));
@@ -296174,10 +296449,11 @@ ${pending.link}`);
296174
296449
  })();
296175
296450
  const rooms = await (async () => {
296176
296451
  try {
296177
- const [{ roomLines: roomLines2 }, invitesModule, roomsModule] = await Promise.all([Promise.resolve().then(() => (init_meRooms(), meRooms_exports)), Promise.resolve().then(() => (init_invites(), invites_exports)), Promise.resolve().then(() => (init_rooms(), rooms_exports))]);
296452
+ const [{ roomLines: roomLines2 }, invitesModule, roomsModule, { proAsksOf: proAsksOf2 }] = await Promise.all([Promise.resolve().then(() => (init_meRooms(), meRooms_exports)), Promise.resolve().then(() => (init_invites(), invites_exports)), Promise.resolve().then(() => (init_rooms(), rooms_exports)), Promise.resolve().then(() => (init_proAsks(), proAsks_exports))]);
296178
296453
  const signer3 = await inviteSigner(await principal2());
296179
- const [page, invited, mineRooms, waiting, agents] = await Promise.all([
296454
+ const [page, calls, invited, mineRooms, waiting, agents] = await Promise.all([
296180
296455
  invitesModule.readMyPage(SITE, signer3).catch(() => void 0),
296456
+ invitesModule.myCalls(SITE, signer3).catch(() => null),
296181
296457
  invitesModule.myInvitations(SITE, signer3).catch(() => null),
296182
296458
  roomsModule.myRooms(SITE, signer3).catch(() => null),
296183
296459
  fetch2(`${SITE}/api/waiting?address=${encodeURIComponent(signer3.address)}`, { signal: AbortSignal.timeout(2e4) }).then((r) => r.ok ? r.json() : null).catch(() => null),
@@ -296188,6 +296464,7 @@ ${pending.link}`);
296188
296464
  "You, as the account area says it:",
296189
296465
  ...roomLines2({
296190
296466
  page: page === void 0 ? null : page === null ? "none" : !verified ? "verify" : page.profile.listed === false ? "private" : "listed",
296467
+ proAsks: calls && "calls" in calls ? proAsksOf2(calls.calls).length : null,
296191
296468
  work: invited && "invited" in invited ? invited.invited.filter((one) => one.answer === "sent").length : null,
296192
296469
  unread: mineRooms && "rooms" in mineRooms ? mineRooms.rooms.reduce((sum2, one) => sum2 + one.unread, 0) : null,
296193
296470
  inbox: Array.isArray(waiting?.waiting) ? waiting.waiting.length : null,
@@ -296259,7 +296536,7 @@ ${pending.link}`);
296259
296536
  const { needsChain: needsChain2, verdictFacts: verdictFacts2 } = await Promise.resolve().then(() => (init_verdictSource(), verdictSource_exports));
296260
296537
  const onChain = needsChain2(ours.evaluationByClaimId) ? await (await Promise.resolve().then(() => (init_claimVerdict(), claimVerdict_exports))).claimVerdictOnChain(ours.claimId) : null;
296261
296538
  const facts = verdictFacts2(ours.evaluationByClaimId, onChain);
296262
- const said3 = verdictSays2(facts.status);
296539
+ const said4 = verdictSays2(facts.status);
296263
296540
  const paid = faceOf2(coinDisplay2(facts.amount ?? void 0), SANDBOX);
296264
296541
  const arrived = paid && facts.amount?.length ? await sharedPays({ amount: facts.amount, is_oracle_payment: receipt.payments?.["approval"]?.is_oracle_payment }, null) : null;
296265
296542
  const proofRaw = facts.verificationProof;
@@ -296276,7 +296553,7 @@ ${pending.link}`);
296276
296553
  return checkFailed2(await readHeldClaim2(ask.oracle.url, key, ours.claimId));
296277
296554
  } : void 0;
296278
296555
  const why = await whyBlock(ours.claimId, proofRaw, ours.agentAddress === mine ? mint : void 0, failed ? { failed } : {});
296279
- return text4([`#${collectionId}: ${said3}.${paid ? ` Paid ${arrived ?? paid.text}.` : ""}`, `answer ${ours.claimId}`, `${SITE}/r/${collectionId}/trace/${encodeURIComponent(ours.claimId)}`, ...why, ...steps, ...tail].join("\n"));
296556
+ return text4([`#${collectionId}: ${said4}.${paid ? ` Paid ${arrived ?? paid.text}.` : ""}`, `answer ${ours.claimId}`, `${SITE}/r/${collectionId}/trace/${encodeURIComponent(ours.claimId)}`, ...why, ...steps, ...tail].join("\n"));
296280
296557
  }
296281
296558
  if (local) {
296282
296559
  server2.registerTool(
@@ -296468,27 +296745,27 @@ Mapping pays for the report. What happens to a mapped pin afterwards is a separa
296468
296745
  }
296469
296746
  },
296470
296747
  async ({ slug: named, clear, ...input }) => {
296471
- const call2 = await Promise.resolve().then(() => (init_call2(), call_exports2));
296748
+ const call3 = await Promise.resolve().then(() => (init_call2(), call_exports2));
296472
296749
  const { CALL_SLUG: CALL_SLUG2 } = await Promise.resolve().then(() => (init_terms(), terms_exports));
296473
- if (call2.typedText(input).some((one) => isTainted(one))) return text4(TAINT_REFUSAL);
296474
- const slug = named?.trim() || call2.nextSlug();
296750
+ if (call3.typedText(input).some((one) => isTainted(one))) return text4(TAINT_REFUSAL);
296751
+ const slug = named?.trim() || call3.nextSlug();
296475
296752
  if (!CALL_SLUG2.test(slug)) return text4(`"${slug}" cannot name a call: lowercase letters, digits and dashes, starting with a letter, 3 to 40 long. Nothing was saved.`);
296476
- const existing = call2.readDraft(slug);
296753
+ const existing = call3.readDraft(slug);
296477
296754
  const posted = existing ? Object.values(existing.posted).some(Boolean) || Boolean(existing.inFlight) : false;
296478
296755
  const changing = clear || Object.values(input).some((value) => value !== void 0);
296479
296756
  if (posted && changing) return text4(`Call "${slug}" is already posted: its terms were frozen with the money. Start a new call with another slug.`);
296480
- const start = clear || !existing ? call2.freshDraft(slug) : existing;
296481
- const merged = call2.mergeDraft(start, input);
296482
- const coin = call2.callCoin(merged.draft, NETWORK2, ASK_DENOM);
296757
+ const start = clear || !existing ? call3.freshDraft(slug) : existing;
296758
+ const merged = call3.mergeDraft(start, input);
296759
+ const coin = call3.callCoin(merged.draft, NETWORK2, ASK_DENOM);
296483
296760
  if (typeof coin !== "string") return text4(`Refused: ${coin.refused}. Nothing was saved.`);
296484
296761
  const refused2 = merged.refused;
296485
296762
  const draft = coin !== ASK_DENOM ? { ...merged.draft, coin } : merged.draft;
296486
- call2.writeDraft(draft);
296763
+ call3.writeDraft(draft);
296487
296764
  const coinSymbol = symbolOf(coin);
296488
296765
  const acting = await principal2();
296489
296766
  const held = await heldBy(acting, coin);
296490
296767
  const holds = held === null ? null : pays(held.reward, coinSymbol);
296491
- const missing2 = call2.missingOf(draft.fields, { symbol: coinSymbol, holds });
296768
+ const missing2 = call3.missingOf(draft.fields, { symbol: coinSymbol, holds });
296492
296769
  const out = [`Draft "${slug}" saved${posted ? " (posted)" : ""}.`];
296493
296770
  if (refused2.length) out.push("", "Not taken:", ...refused2.map((one) => ` - ${one}`));
296494
296771
  if (missing2.length) {
@@ -296497,7 +296774,7 @@ Mapping pays for the report. What happens to a mapped pin afterwards is a separa
296497
296774
  "Still needed, in this order. Ask the person, a group at a time, in their words; never write the brief for them:",
296498
296775
  ...missing2.flatMap((one, index) => [` ${index + 1}. ${one.field}: ${one.question}`, ` e.g. ${one.example}`])
296499
296776
  );
296500
- const optional5 = call2.optionalOf(draft.fields, originOf(NETWORK2));
296777
+ const optional5 = call3.optionalOf(draft.fields, originOf(NETWORK2));
296501
296778
  if (optional5.length) out.push("", "Optional, not given yet:", ...optional5.map((one) => ` - ${one}`));
296502
296779
  return text4(out.join("\n"));
296503
296780
  }
@@ -296507,20 +296784,20 @@ Mapping pays for the report. What happens to a mapped pin afterwards is a separa
296507
296784
  const checker = await callChecker2(draft.fields.kind === "review");
296508
296785
  if (checker.fee && checker.fee.denom !== coin) return text4(`Refused: ${checker.name} is paid in another coin than this call pays in, and a review pays in its verifier's coin. Start a new review.`);
296509
296786
  const perCheck = checker.fee ? false : await callPerCheck(checker.address);
296510
- const priced = call2.callShare(draft.fields, call2.callShares(draft.fields) ? await callSplit() : null);
296787
+ const priced = call3.callShare(draft.fields, call3.callShares(draft.fields) ? await callSplit() : null);
296511
296788
  if ("unread" in priced) {
296512
296789
  out.push("", "Not priced yet: 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. The draft is saved; call draft_call again in a minute.");
296513
296790
  return text4(out.join("\n"));
296514
296791
  }
296515
296792
  const proAsk = draft.fields.kind === "review";
296516
- const plan = call2.callPlan(draft, { poster: shortPoster, checkerLegBase: (terms) => checker.fee ? checker.fee.base : perCheck ? 0 : checkerLegBase2(FEE_DENOM, terms, CHECK_REWARD), oracle: checker.address || "the verifier", share: priced.share, feeInReward: Boolean(checker.fee) || coin === FEE_DENOM });
296793
+ const plan = call3.callPlan(draft, { poster: shortPoster, checkerLegBase: (terms) => checker.fee ? checker.fee.base : perCheck ? 0 : checkerLegBase2(FEE_DENOM, terms, CHECK_REWARD), oracle: checker.address || "the verifier", share: priced.share, feeInReward: Boolean(checker.fee) || coin === FEE_DENOM });
296517
296794
  const feeTotal = plan.legs.reduce((sum2, one) => sum2 + one.feeBase, 0);
296518
296795
  const finalOk = draft.fields.kind === "review" ? acting?.principal ?? null : null;
296519
- const preview = call2.legTerms(draft, "entries", { poster: shortPoster, dates: plan.dates, oracle: { kind: "oracle", address: checker.address || "the verifier" }, approver: finalOk, share: plan.share });
296520
- const twoCoins = acting && feeTotal > 0 ? `Can't post as ${acting.principal}: ${call2.callTwoCoins}.` : null;
296796
+ const preview = call3.legTerms(draft, "entries", { poster: shortPoster, dates: plan.dates, oracle: { kind: "oracle", address: checker.address || "the verifier" }, approver: finalOk, share: plan.share });
296797
+ const twoCoins = acting && feeTotal > 0 ? `Can't post as ${acting.principal}: ${call3.callTwoCoins}.` : null;
296521
296798
  const { capCoinRefusal: capCoinRefusal2, capIn: capIn2 } = await Promise.resolve().then(() => (init_hq(), hq_exports));
296522
296799
  const otherCoin = capCoinRefusal2(acting, coin, checker.fee ? `${SITE}/connect` : void 0);
296523
- const capped4 = call2.capWords(plan.legs, CAP_BASE, coinSymbol, NETWORK2);
296800
+ const capped4 = call3.capWords(plan.legs, CAP_BASE, coinSymbol, NETWORK2);
296524
296801
  const keyOnly = !acting && feeTotal > 0;
296525
296802
  const blocked = capped4.length > 0 || Boolean(otherCoin) || Boolean(twoCoins) && draft.fields.kind !== "review";
296526
296803
  const m = draft.fields.money;
@@ -296540,15 +296817,15 @@ Mapping pays for the report. What happens to a mapped pin afterwards is a separa
296540
296817
  !hire && m.prize < m.entryEach ? `The prize (${face(m.prize, coinSymbol)}) is less than one entry earns (${face(m.entryEach, coinSymbol)}).` : "",
296541
296818
  draft.fields.access === "invite" && !draft.fields.invite?.length ? proAsk ? "Nobody invited yet: find_pro suggests verified pros; add them with invite now, or invite_to_call after it posts." : 'By invitation, and nobody invited yet: add invite (addresses, @handles, "link") now, or invite_to_call after it posts.' : "",
296542
296819
  draft.fields.access === "apply" ? "By application: people apply on the call's page or with apply_to_call; you say yes with decide_application before they can enter." : "",
296543
- ...call2.balanceWarnings(held, { totalBase: plan.totalBase, feeTotal, symbol: coinSymbol, network: NETWORK2, feeWords }),
296820
+ ...call3.balanceWarnings(held, { totalBase: plan.totalBase, feeTotal, symbol: coinSymbol, network: NETWORK2, feeWords }),
296544
296821
  acting?.cap && !otherCoin && Number(capIn2(acting, coin)?.remainingBase ?? 0) < plan.totalBase ? `Their cap has ${pays(Number(capIn2(acting, coin)?.remainingBase ?? 0), coinSymbol)} left; the call locks ${pays(plan.totalBase, coinSymbol)}. They raise it at ${SITE}/connect.` : "",
296545
- keyOnly ? `Not connected, and a connection would not carry this call: ${call2.callTwoCoins}. With plain_key: true it posts as this key itself, ${await address2()}, from its own money.` : !acting ? `Not connected: post_call refuses until the person connects this key (connect_account gives them the link). For a rehearsal, plain_key: true posts as this key itself, ${await address2()}, from its own money.` : ""
296822
+ keyOnly ? `Not connected, and a connection would not carry this call: ${call3.callTwoCoins}. With plain_key: true it posts as this key itself, ${await address2()}, from its own money.` : !acting ? `Not connected: post_call refuses until the person connects this key (connect_account gives them the link). For a rehearsal, plain_key: true posts as this key itself, ${await address2()}, from its own money.` : ""
296546
296823
  ].filter(Boolean);
296547
296824
  out.push(
296548
296825
  "",
296549
296826
  blocked ? "Drafted, but post_call would refuse it as it stands (the warnings say why). This is the call as an entrant's AI will read it:" : "Ready. This is the call as an entrant's AI will read it:",
296550
296827
  "",
296551
- call2.callReadout(preview, { id: "(the entries ask, once posted)", symbol: coinSymbol, network: NETWORK2 }),
296828
+ call3.callReadout(preview, { id: "(the entries ask, once posted)", symbol: coinSymbol, network: NETWORK2 }),
296552
296829
  "",
296553
296830
  "What each leg locks:",
296554
296831
  ...legRows,
@@ -296562,7 +296839,7 @@ Mapping pays for the report. What happens to a mapped pin afterwards is a separa
296562
296839
  `Who may enter: ${draft.fields.access === "invite" ? `by invitation only${draft.fields.invite?.length ? `. ${draft.fields.invite.length} people will be invited when the Ask is posted${draft.fields.inviteNote ? ", each with your private note" : ""}` : ""}` : draft.fields.access === "apply" ? "by application, listed on the board" : "anyone, listed on the board"}.`,
296563
296840
  ...draft.fields.kind === "review" ? [
296564
296841
  `A pro ask: every entry is a review report with screenshots (submit_work's report and files), checked by ${checker.name ?? "the AI"} on the lines${acting ? `, then ${acting.principal} gives final approval before anyone is paid` : `; posted from this key itself, ${checker.name ?? "the AI"} decides alone and passing reports are paid as they are judged`}.`,
296565
- draft.posted.entries ? `Its page: ${EXPERT_SITE}/pro/reviews/${draft.posted.entries.id}` : "Its page is named by the pro ask's number, given once it posts."
296842
+ draft.posted.entries ? `Its page: ${EXPERT_SITE}/me/pro-asks/${draft.posted.entries.id}` : "Its page is named by the pro ask's number, given once it posts."
296566
296843
  ] : [],
296567
296844
  ...warnings2.length ? ["", "Warnings:", ...warnings2.map((one) => ` - ${one}`)] : [],
296568
296845
  "",
@@ -296585,17 +296862,17 @@ Mapping pays for the report. What happens to a mapped pin afterwards is a separa
296585
296862
  },
296586
296863
  async ({ slug, confirm, plain_key, pay_by }) => {
296587
296864
  const card = pay_by === "card";
296588
- const call2 = await Promise.resolve().then(() => (init_call2(), call_exports2));
296589
- const found = call2.readDraft(slug);
296865
+ const call3 = await Promise.resolve().then(() => (init_call2(), call_exports2));
296866
+ const found = call3.readDraft(slug);
296590
296867
  if (!found) return text4(`No draft called "${slug}". Start one with draft_call.`);
296591
296868
  const review = found.fields.kind === "review";
296592
296869
  const checker = await callChecker2(review);
296593
- const linkOf = (posted2) => review ? `${EXPERT_SITE}/pro/reviews/${posted2.entries?.id ?? slug}` : `${SITE}/opencall/${slug}`;
296594
- const settled = found.inFlight ? await call2.settleInFlight(slug, call2.indexLookup) : null;
296870
+ const linkOf = (posted2) => review ? `${EXPERT_SITE}/me/pro-asks/${posted2.entries?.id ?? slug}` : `${SITE}/opencall/${slug}`;
296871
+ const settled = found.inFlight ? await call3.settleInFlight(slug, call3.indexLookup) : null;
296595
296872
  if (settled?.state === "pending") return text4(settled.words);
296596
296873
  if (settled?.state === "landed") {
296597
296874
  nudge("hire", settled.id, checker.at);
296598
- const after2 = call2.nextLeg(settled.draft);
296875
+ const after2 = call3.nextLeg(settled.draft);
296599
296876
  return text4(
296600
296877
  [
296601
296878
  `The earlier post landed: ${LEG_WORDS[settled.leg]} is #${settled.id}. It is recorded, and nothing was posted twice.`,
@@ -296604,14 +296881,14 @@ Mapping pays for the report. What happens to a mapped pin afterwards is a separa
296604
296881
  );
296605
296882
  }
296606
296883
  const draft = settled?.draft ?? found;
296607
- const coin = call2.callCoin(draft, NETWORK2, ASK_DENOM);
296884
+ const coin = call3.callCoin(draft, NETWORK2, ASK_DENOM);
296608
296885
  if (typeof coin !== "string") return text4(`Refused: ${coin.refused}. Nothing was posted.`);
296609
296886
  const coinSymbol = symbolOf(coin);
296610
- const next = call2.nextLeg(draft);
296887
+ const next = call3.nextLeg(draft);
296611
296888
  const ids = ["prize", "runnersUp", "entries"].flatMap((leg2) => draft.posted[leg2] ? [`${LEG_WORDS[leg2]} #${draft.posted[leg2].id}`] : []);
296612
296889
  if (!next) return text4(`Everything is posted: ${ids.join(", ")}.
296613
296890
  The call: ${linkOf(draft.posted)}`);
296614
- if (!call2.isReady(draft.fields)) return text4(`"${slug}" is not ready: ${call2.missingOf(draft.fields, { symbol: coinSymbol, holds: null }).map((one) => one.field).join(", ")} still missing. Finish it with draft_call.`);
296891
+ if (!call3.isReady(draft.fields)) return text4(`"${slug}" is not ready: ${call3.missingOf(draft.fields, { symbol: coinSymbol, holds: null }).map((one) => one.field).join(", ")} still missing. Finish it with draft_call.`);
296615
296892
  const cannot = await unjudged();
296616
296893
  if (cannot) return text4(cannot);
296617
296894
  if (!checker.address) return text4("No verifier is configured on this deployment, so nothing could judge the entries. Refusing rather than posting a call nobody can settle.");
@@ -296626,15 +296903,15 @@ Then call post_call again. Nothing was posted.`);
296626
296903
  const poster = acting?.principal ?? await address2();
296627
296904
  if (checker.fee && checker.fee.denom !== coin) return text4(`Refused: ${checker.name} is paid in another coin than this call pays in, and a review pays in its verifier's coin. Start a new review. Nothing was posted.`);
296628
296905
  const perCheck = checker.fee ? false : await callPerCheck(checker.address);
296629
- const split3 = call2.callShares(draft.fields) ? await callSplit() : null;
296630
- const priced = call2.callShare(draft.fields, split3);
296631
- if ("unread" in priced) return text4(call2.SHARE_UNREAD);
296632
- const plan = call2.callPlan(draft, { poster: `${poster.slice(0, 10)}\u2026${poster.slice(-4)}`, checkerLegBase: (terms) => checker.fee ? checker.fee.base : perCheck ? 0 : checkerLegBase2(FEE_DENOM, terms, CHECK_REWARD), oracle: checker.address, share: priced.share, feeInReward: Boolean(checker.fee) || coin === FEE_DENOM });
296906
+ const split3 = call3.callShares(draft.fields) ? await callSplit() : null;
296907
+ const priced = call3.callShare(draft.fields, split3);
296908
+ if ("unread" in priced) return text4(call3.SHARE_UNREAD);
296909
+ const plan = call3.callPlan(draft, { poster: `${poster.slice(0, 10)}\u2026${poster.slice(-4)}`, checkerLegBase: (terms) => checker.fee ? checker.fee.base : perCheck ? 0 : checkerLegBase2(FEE_DENOM, terms, CHECK_REWARD), oracle: checker.address, share: priced.share, feeInReward: Boolean(checker.fee) || coin === FEE_DENOM });
296633
296910
  const feeTotal = plan.legs.reduce((sum2, one) => sum2 + one.feeBase, 0);
296634
296911
  const total = pays(plan.totalBase, coinSymbol);
296635
296912
  const { feeLine: feeLine2 } = await Promise.resolve().then(() => (init_feeLine(), feeLine_exports));
296636
296913
  const moneySentence = review && plan.share ? feeLine2({ split: plan.share, net: draft.fields.money.entryEach, symbol: coinSymbol, network: NETWORK2 }) : null;
296637
- if (acting && feeTotal > 0) return text4(`Refused: ${call2.callTwoCoins}.${review ? ` ${PLAIN_REVIEW}` : ""} Nothing was posted.`);
296914
+ if (acting && feeTotal > 0) return text4(`Refused: ${call3.callTwoCoins}.${review ? ` ${PLAIN_REVIEW}` : ""} Nothing was posted.`);
296638
296915
  const approver = review && acting ? acting.principal : null;
296639
296916
  if (approver) {
296640
296917
  const notReady = await approverRefusal(approver, async (who) => (await Promise.resolve().then(() => (init_personReview(), personReview_exports))).approverReady(who, { self: true }));
@@ -296668,21 +296945,21 @@ Then call post_call again. Nothing was posted.`);
296668
296945
  actingNote(acting) ?? (review ? "Posting from your own account (this key), not the person's account; the AI decides each report alone, with no final OK from the person." : `Posting as this key, ${poster}.`),
296669
296946
  ...pick2 ? [pick2] : [],
296670
296947
  `Spent today (call): ${spentWords("call", coinSymbol)}. Every tool together: ${spentAllWords()}.`,
296671
- ...call2.capWords(plan.legs.filter((one) => !draft.posted[one.leg]), CAP_BASE, coinSymbol, NETWORK2),
296672
- ...call2.balanceWarnings(held2, { totalBase: plan.totalBase, feeTotal, symbol: coinSymbol, network: NETWORK2, feeWords }),
296948
+ ...call3.capWords(plan.legs.filter((one) => !draft.posted[one.leg]), CAP_BASE, coinSymbol, NETWORK2),
296949
+ ...call3.balanceWarnings(held2, { totalBase: plan.totalBase, feeTotal, symbol: coinSymbol, network: NETWORK2, feeWords }),
296673
296950
  "",
296674
296951
  `To go ahead, call again with confirm: "${total}".`
296675
296952
  ].join("\n")
296676
296953
  );
296677
296954
  }
296678
- if (!call2.confirms(confirm, plan.totalBase, coinSymbol)) return text4(`Refused: confirm said "${confirm}" but the call locks ${total}. Preview it again.`);
296679
- if (call2.overCap(leg, CAP_BASE)) return text4(`Refused: this leg locks ${pays(leg.escrowBase, coinSymbol)}, over your own ${face(MAX_PER_ASK, coinSymbol)} per-ask cap (OPENHANDS_MAX_PER_ASK_USD, which you set: raise or remove it where you set it). Paying by card (pay_by "card") is not capped.`);
296955
+ if (!call3.confirms(confirm, plan.totalBase, coinSymbol)) return text4(`Refused: confirm said "${confirm}" but the call locks ${total}. Preview it again.`);
296956
+ if (call3.overCap(leg, CAP_BASE)) return text4(`Refused: this leg locks ${pays(leg.escrowBase, coinSymbol)}, over your own ${face(MAX_PER_ASK, coinSymbol)} per-ask cap (OPENHANDS_MAX_PER_ASK_USD, which you set: raise or remove it where you set it). Paying by card (pay_by "card") is not capped.`);
296680
296957
  if (ids.length === 0) {
296681
- const taken = await fetch2(`${SITE}/api/board?campaign=${encodeURIComponent(call2.tagOf(draft))}&size=5`, { signal: AbortSignal.timeout(15e3) }).then((response) => response.ok ? response.json() : null).catch(() => null);
296958
+ const taken = await fetch2(`${SITE}/api/board?campaign=${encodeURIComponent(call3.tagOf(draft))}&size=5`, { signal: AbortSignal.timeout(15e3) }).then((response) => response.ok ? response.json() : null).catch(() => null);
296682
296959
  if (taken?.rows?.length) return text4(`Refused: "${slug}" already names a call with open Asks on this board. Draft it under another slug with draft_call. Nothing was posted.`);
296683
296960
  }
296684
296961
  const { balancesOfStrict: balancesOfStrict2 } = await Promise.resolve().then(() => (init_balance(), balance_exports));
296685
- const refusedBefore = await call2.preCheck(leg, {
296962
+ const refusedBefore = await call3.preCheck(leg, {
296686
296963
  acting,
296687
296964
  poster,
296688
296965
  askDenom: coin,
@@ -296699,7 +296976,7 @@ Then call post_call again. Nothing was posted.`);
296699
296976
  const key = await loadKey2();
296700
296977
  let posted;
296701
296978
  try {
296702
- posted = await call2.postNextLeg(slug, {
296979
+ posted = await call3.postNextLeg(slug, {
296703
296980
  site: SITE,
296704
296981
  askDenom: coin,
296705
296982
  checker: checker.address,
@@ -296715,10 +296992,10 @@ Then call post_call again. Nothing was posted.`);
296715
296992
  feeSplit: split3
296716
296993
  });
296717
296994
  } catch (error54) {
296718
- if (error54 instanceof call2.InFlightError || error54 instanceof call2.PostRefused) return text4(error54.message);
296995
+ if (error54 instanceof call3.InFlightError || error54 instanceof call3.PostRefused) return text4(error54.message);
296719
296996
  if (isUnanchored(error54)) return text4(unanchoredWords(error54));
296720
296997
  if (error54 instanceof Error && error54.name === "TxFailed") {
296721
- if (call2.feeUnpaid(error54, coin)) return text4(`Nothing moved: this agent's key could not pay the network fee for ${LEG_WORDS[next]}. Call post_call again in a minute; it arranges the fee before it signs anything. If it is refused again, tell the person the network fee could not be arranged just now.`);
296998
+ if (call3.feeUnpaid(error54, coin)) return text4(`Nothing moved: this agent's key could not pay the network fee for ${LEG_WORDS[next]}. Call post_call again in a minute; it arranges the fee before it signs anything. If it is refused again, tell the person the network fee could not be arranged just now.`);
296722
296999
  return text4(`The network refused ${LEG_WORDS[next]}: ${error54.message}. Nothing moved. Fix that (often what the account holds, or its cap) and call post_call again.`);
296723
297000
  }
296724
297001
  return text4(
@@ -296728,7 +297005,7 @@ Then call post_call again. Nothing was posted.`);
296728
297005
  if ("done" in posted) return text4(`Everything is posted.
296729
297006
  The call: ${linkOf(posted.draft.posted)}`);
296730
297007
  const done = order2.filter((one) => posted.draft.posted[one]).length;
296731
- const after = call2.nextLeg(posted.draft);
297008
+ const after = call3.nextLeg(posted.draft);
296732
297009
  const hire = posted.draft.fields.mode === "hire";
296733
297010
  const held = posted.screen?.verdict === "hold" ? heldWords(posted.screen.reason) : null;
296734
297011
  const invited = !after && posted.draft.fields.access && posted.draft.fields.access !== "public" ? await writeDraftInvites(posted.draft, posted.id, acting) : null;
@@ -296951,7 +297228,7 @@ ${allowLine(SITE, posted.id, approver, acting?.principal ?? null)}` : `Every rep
296951
297228
  const answer = await invitesModule.myInvitations(SITE, signer3);
296952
297229
  if ("refused" in answer) return text4(`Refused: ${answer.refused}`);
296953
297230
  const missed = answer.missed ? `Not shown: ${answer.missed}.` : "";
296954
- if (answer.invited.length === 0) return text4([`Nothing yet: no poster has put this key${signer3.principal && signer3.principal !== signer3.address ? ", or the person it acts for," : ""} on a list. A person's own invitations are also on the site, signed in: ${EXPERT_SITE}/pro/work for reviews, ${SITE}/opencall for other calls.`, missed].filter(Boolean).join("\n"));
297231
+ if (answer.invited.length === 0) return text4([`Nothing yet: no poster has put this key${signer3.principal && signer3.principal !== signer3.address ? ", or the person it acts for," : ""} on a list. A person's own invitations are also on the site, signed in: ${EXPERT_SITE}/me/work for pro asks, ${SITE}/opencall for other calls.`, missed].filter(Boolean).join("\n"));
296955
297232
  const rooms = await roomsModule.myRooms(SITE, signer3).catch(() => ({ refused: "unreachable" }));
296956
297233
  const roomOf = "refused" in rooms ? null : new Map(rooms.rooms.filter((one) => one.role === "pro").map((one) => [one.collectionId, one]));
296957
297234
  const me = roomsModule.actorOf(signer3);
@@ -296959,7 +297236,7 @@ ${allowLine(SITE, posted.id, approver, acting?.principal ?? null)}` : `Every rep
296959
297236
  [
296960
297237
  "Invited to:",
296961
297238
  ...answer.invited.flatMap((one) => [
296962
- ` #${one.collectionId}${one.title ? ` \xB7 ${one.title}` : ""}${one.answer ? ` \xB7 ${invitesModule.answerLine(one)}` : ""}${one.campaign?.startsWith("call-") ? ` \xB7 ${isReviewTitle(one.title) ? `${EXPERT_SITE}/pro/work/${one.collectionId}` : askPage(SITE, one.collectionId, { campaign: one.campaign, title: one.title })}` : ""} \xB7 ${one.answer === "sent" ? `accept_invitation "${one.collectionId}" or decline_invitation` : `read_ask "${one.collectionId}"`}`,
297239
+ ` #${one.collectionId}${one.title ? ` \xB7 ${one.title}` : ""}${one.answer ? ` \xB7 ${invitesModule.answerLine(one)}` : ""}${one.campaign?.startsWith("call-") ? ` \xB7 ${isReviewTitle(one.title) ? `${EXPERT_SITE}/me/work/${one.collectionId}` : askPage(SITE, one.collectionId, { campaign: one.campaign, title: one.title })}` : ""} \xB7 ${one.answer === "sent" ? `accept_invitation "${one.collectionId}" or decline_invitation` : `read_ask "${one.collectionId}"`}`,
296963
297240
  ...one.note ? [` The poster's note to you: ${asData("invitation-note", one.note)}`] : [],
296964
297241
  ...roomOf ? [roomsModule.invitationRoomLine(one, roomOf.get(one.collectionId) ?? null, { site: SITE, me })].filter((line2) => Boolean(line2)) : []
296965
297242
  ]),
@@ -296973,12 +297250,78 @@ ${allowLine(SITE, posted.id, approver, acting?.principal ?? null)}` : `Every rep
296973
297250
  const peeked = await invitesModule.peekInvitation(SITE, which.token).catch(() => null);
296974
297251
  return peeked ? `pro ask #${peeked.collectionId}${peeked.title ? ` (${peeked.title.replace(/^Expert review:\s*/, "")})` : ""}` : "the pro ask this link names";
296975
297252
  };
297253
+ if (offered("my_pro_asks")) server2.registerTool("my_pro_asks", { ...meta3("my_pro_asks"), inputSchema: {} }, async () => {
297254
+ const [invitesModule, proAsksModule] = await Promise.all([Promise.resolve().then(() => (init_invites(), invites_exports)), Promise.resolve().then(() => (init_proAsks(), proAsks_exports))]);
297255
+ const signer3 = await inviteSigner(await principal2());
297256
+ const answer = await invitesModule.myCalls(SITE, signer3);
297257
+ if ("refused" in answer) return text4(`Refused: ${answer.refused}`);
297258
+ const missed = answer.missed ? `Not shown: ${answer.missed}.` : "";
297259
+ const asks = proAsksModule.proAsksOf(answer.calls);
297260
+ if (asks.length === 0) return text4([`No pro asks yet${signer3.principal && signer3.principal !== signer3.address ? " from this key or the person it acts for" : ""}. draft_call with kind "review" sets one up.`, missed].filter(Boolean).join("\n"));
297261
+ const owners = [...new Set(asks.map((one) => one.owner ?? signer3.address))];
297262
+ const [held, waiting] = await Promise.all([
297263
+ (async () => {
297264
+ const { asksHolding: asksHolding2 } = await Promise.resolve().then(() => (init_onAsks(), onAsks_exports));
297265
+ const { graphqlUrl: graphqlUrl4, restUrl: restUrl2 } = await Promise.resolve().then(() => (init_env(), env_exports));
297266
+ const lists = await Promise.all(owners.map((who) => asksHolding2(who, { graphqlUrl: graphqlUrl4(), restUrl: restUrl2() })));
297267
+ return new Map(lists.flat().map((one) => [one.collectionId, pays(one.held, "upay")]));
297268
+ })().catch(() => null),
297269
+ Promise.all(owners.map((who) => fetch2(`${SITE}/api/waiting?address=${encodeURIComponent(who)}`, { signal: AbortSignal.timeout(2e4) }).then((r) => r.ok ? r.json() : null))).then((answers) => answers.flatMap((one) => one?.waiting ?? [])).catch(() => null)
297270
+ ]);
297271
+ return text4([`Pro asks (${asks.length}):`, ...proAsksModule.proAskLines(EXPERT_SITE, asks, { held, waiting }), missed].filter(Boolean).join("\n"));
297272
+ });
297273
+ if (offered("approve_report")) server2.registerTool(
297274
+ "approve_report",
297275
+ {
297276
+ ...meta3("approve_report"),
297277
+ inputSchema: {
297278
+ collectionId: external_exports.string().regex(/^\d+$/).describe("The pro ask's number (my_pro_asks shows it)."),
297279
+ claimId: external_exports.string().min(1).max(128).describe("The report's id: the claim my_pro_asks or the ask's page names."),
297280
+ confirm: external_exports.boolean().optional().describe("Leave out to see what approving pays and whose OK it is. true approves.")
297281
+ }
297282
+ },
297283
+ async ({ collectionId, claimId, confirm }) => {
297284
+ const proAsksModule = await Promise.resolve().then(() => (init_proAsks(), proAsks_exports));
297285
+ const mine = await address2();
297286
+ const acting = await principal2();
297287
+ const who = acting?.principal ?? mine;
297288
+ const queue = await fetch2(`${SITE}/api/waiting?address=${encodeURIComponent(who)}`, { signal: AbortSignal.timeout(2e4) }).then((r) => r.ok ? r.json() : null).catch(() => null);
297289
+ if (!queue || queue.unavailable) return text4("Refused: the reports waiting for an OK could not be read just now. Nothing was sent; try again in a minute.");
297290
+ const item = (queue.waiting ?? []).find((one) => one.collectionId === collectionId && one.claimId === claimId);
297291
+ if (!item) return text4(`Nothing to approve: report ${claimId} on pro ask #${collectionId} is not waiting for ${who === mine ? "this key's" : `${who}'s`} OK. It may be approved already, still being checked, or another account's to approve. The report: ${proAsksModule.reportPage(EXPERT_SITE, collectionId, claimId)}`);
297292
+ const approver = item.approver ?? who;
297293
+ const canSign = approver === mine;
297294
+ const paid = item.pays ? face(item.pays.value, item.pays.symbol) : null;
297295
+ const facts = { collectionId, claimId, pro: item.agentAddress, pays: paid, approver, canSign };
297296
+ if (!confirm || !canSign) return text4(proAsksModule.approvePreview(EXPERT_SITE, facts));
297297
+ const ask = await readJson3(`${SITE}/api/oracle/${encodeURIComponent(collectionId)}`).catch(() => null);
297298
+ if (!ask?.oracle?.url) return text4("Refused: the verifier for this pro ask could not be reached. Nothing was sent; try again in a minute.");
297299
+ const review = await Promise.resolve().then(() => (init_personReview(), personReview_exports));
297300
+ const key = { address: mine, mnemonic: (await loadKey2()).mnemonic };
297301
+ const held = await review.readHeldClaim(ask.oracle.url, key, claimId);
297302
+ if (!held?.decision || held.decision.status !== "pending_review") return text4(`Nothing to approve: the verifier has no decision waiting on report ${claimId}${held?.decision?.status ? ` (it is ${held.decision.status.replace(/_/g, " ")})` : ""}. Nothing was sent.`);
297303
+ const protocol = item.protocol ?? ask.protocol ?? null;
297304
+ const { engineUrl: engineUrl2 } = await Promise.resolve().then(() => (init_engineUrl(), engineUrl_exports));
297305
+ const questions = protocol && engineUrl2() ? await review.reviewQuestions(engineUrl2(), protocol, held.decision.pendingTasks).catch(() => null) : null;
297306
+ if (questions?.some((one) => one.answer.type !== "boolean")) return text4(`Not approved: this report has a question that is not a yes or no, so its OK is given on the report's page: ${proAsksModule.reportPage(EXPERT_SITE, collectionId, claimId)}#decide. Nothing was sent.`);
297307
+ const answers = Object.fromEntries(held.decision.pendingTasks.map((task) => [task, true]));
297308
+ const receipt = await askReceipt(collectionId);
297309
+ if (receipt?.owner === mine) {
297310
+ const ends = ask.endsAt ? Math.floor(Date.parse(ask.endsAt) / 1e3) : null;
297311
+ await review.ensureReviewing({ owner: key, oracleUrl: ask.oracle.url, collectionId, reviewer: mine, endsAt: Number.isFinite(ends) ? ends : null }).catch(() => null);
297312
+ }
297313
+ const sent = await review.sendReview({ reviewer: key, oracleUrl: ask.oracle.url, collectionId, claimId, answers });
297314
+ if (!sent.ok) return text4(`Not approved: ${sent.why}${sent.detail ? ` (${sent.detail})` : ""}. Nothing was paid.`);
297315
+ return text4(`Approved report ${claimId} on pro ask #${collectionId}. The verifier records the OK and pays ${item.agentAddress}${paid ? ` ${paid}` : ""} on the ledger in a minute or two.
297316
+ The report: ${proAsksModule.reportPage(EXPERT_SITE, collectionId, claimId)}`);
297317
+ }
297318
+ );
296976
297319
  if (offered("accept_invitation")) server2.registerTool(
296977
297320
  "accept_invitation",
296978
297321
  {
296979
297322
  ...meta3("accept_invitation"),
296980
297323
  inputSchema: {
296981
- invitation: external_exports.string().min(1).max(512).describe("The invitation: its link (\u2026/pro/i/\u2026), or the pro ask's number (my_invitations shows it)."),
297324
+ invitation: external_exports.string().min(1).max(512).describe("The invitation: its link (\u2026/i/\u2026), or the pro ask's number (my_invitations shows it)."),
296982
297325
  confirm: external_exports.boolean().optional().describe("false (the default) previews; true accepts, once the person has said yes.")
296983
297326
  }
296984
297327
  },
@@ -297002,7 +297345,7 @@ ${allowLine(SITE, posted.id, approver, acting?.principal ?? null)}` : `Every rep
297002
297345
  return text4(
297003
297346
  [
297004
297347
  done.state === "already" ? `Already accepted #${id}.` : `Accepted #${id}${acting ? ` as ${acting.principal}` : ""}. The builder knows.`,
297005
- `Your job page: ${EXPERT_SITE}/pro/work/${id}`,
297348
+ `Your job page: ${EXPERT_SITE}/me/work/${id}`,
297006
297349
  `Next: read_ask "${id}" for the brief, read_messages collectionId "${id}" for the builder's note, then submit_work when the person says so.`
297007
297350
  ].join("\n")
297008
297351
  );
@@ -297013,7 +297356,7 @@ ${allowLine(SITE, posted.id, approver, acting?.principal ?? null)}` : `Every rep
297013
297356
  {
297014
297357
  ...meta3("decline_invitation"),
297015
297358
  inputSchema: {
297016
- invitation: external_exports.string().min(1).max(512).describe("The invitation: its link (\u2026/pro/i/\u2026), or the pro ask's number (my_invitations shows it)."),
297359
+ invitation: external_exports.string().min(1).max(512).describe("The invitation: its link (\u2026/i/\u2026), or the pro ask's number (my_invitations shows it)."),
297017
297360
  note: external_exports.string().max(200).optional().describe("A line for the builder, in the person's words: only they read it. Optional."),
297018
297361
  confirm: external_exports.boolean().optional().describe("false (the default) previews; true declines, once the person has said yes.")
297019
297362
  }
@@ -297105,7 +297448,7 @@ The room's page: ${roomPage(SITE, collectionId, page?.profile.handle ?? sent.pro
297105
297448
  const pageInput = external_exports.object({
297106
297449
  verificationServices: external_exports.array(verificationServiceSchema).max(6).optional(),
297107
297450
  verificationCredentials: external_exports.array(credentialReferenceSchema).max(12).optional(),
297108
- handle: external_exports.string().max(30).describe("Lowercase letters, digits and dashes, 3 to 30, starting with a letter. The page's address: /pro/pros/<handle>."),
297451
+ handle: external_exports.string().max(30).describe("Lowercase letters, digits and dashes, 3 to 30, starting with a letter. The page's address: /pros/<handle>."),
297109
297452
  name: external_exports.string().max(80),
297110
297453
  headline: external_exports.string().max(160).optional().describe("One line: what they do, in their words."),
297111
297454
  about: external_exports.string().max(2e3).optional().describe("The summary, a few sentences in their words."),
@@ -297209,12 +297552,12 @@ No private link was made: ${link5.refused}.`;
297209
297552
  const page = await invitesModule.readMyPage(SITE, await inviteSigner(acting));
297210
297553
  if (!page) return text4("No pro page yet. Next: connect_linkedin (about a minute).");
297211
297554
  return text4(`${invitesModule.pageWords(page, SITE)}
297212
- ${page.profile.listed === false ? `Your page is private. Preview it at ${EXPERT_SITE}/pro/profile/preview (only you can see it), or ask me for your private link.
297555
+ ${page.profile.listed === false ? `Your page is private. Preview it at ${EXPERT_SITE}/me/page/preview (only you can see it), or ask me for your private link.
297213
297556
  ` : ""}${page.shared ? 'Private link: there is one (it is shown only when made; set_my_page with share_link: "replace" gives a new one and switches the old one off).' : 'Private link: none (set_my_page with share_link: "create" makes one).'}
297214
297557
 
297215
297558
  ${page.linkedin?.credentialUrl || page.linkedin?.credential ? `${credentialWords(page.linkedin, page.profile.listed !== false)}
297216
297559
 
297217
- ` : ""}Edit the profile at ${EXPERT_SITE}/pro/profile.${page.linkedin ? "" : " Next: connect_linkedin verifies it, so you can be invited to pro asks."}`);
297560
+ ` : ""}Edit the profile at ${EXPERT_SITE}/me/page/edit.${page.linkedin ? "" : " Next: connect_linkedin verifies it, so you can be invited to pro asks."}`);
297218
297561
  });
297219
297562
  if (offered("find_pro")) server2.registerTool(
297220
297563
  "find_pro",
@@ -297244,7 +297587,7 @@ ${page.linkedin?.credentialUrl || page.linkedin?.credential ? `${credentialWords
297244
297587
  return text4(pros.prosWords(found, { site: SITE, q, available }));
297245
297588
  }
297246
297589
  );
297247
- const credentialWords = (linkedin, listed) => linkedin?.credentialUrl && listed ? `You also have a LinkedIn credential: it shows you logged in to this LinkedIn account, and any app can check it. Its public link: ${linkedin.credentialUrl}. Download it at ${EXPERT_SITE}/pro/profile.` : `You also have a LinkedIn credential: it shows you logged in to this LinkedIn account, and any app can check it. ${listed && !linkedin?.credential && !linkedin?.credentialUrl ? "It appears on your page once the page is published." : "Only you can see it while your page is private; it goes public when the page does."} Download it at ${EXPERT_SITE}/pro/profile.`;
297590
+ const credentialWords = (linkedin, listed) => linkedin?.credentialUrl && listed ? `You also have a LinkedIn credential: it shows you logged in to this LinkedIn account, and any app can check it. Its public link: ${linkedin.credentialUrl}. Download it at ${EXPERT_SITE}/me/page/edit.` : `You also have a LinkedIn credential: it shows you logged in to this LinkedIn account, and any app can check it. ${listed && !linkedin?.credential && !linkedin?.credentialUrl ? "It appears on your page once the page is published." : "Only you can see it while your page is private; it goes public when the page does."} Download it at ${EXPERT_SITE}/me/page/edit.`;
297248
297591
  if (offered("connect_linkedin")) server2.registerTool(
297249
297592
  "connect_linkedin",
297250
297593
  {
@@ -297293,7 +297636,7 @@ ${asData("linkedin", JSON.stringify(prefill, null, 2))}`
297293
297636
  const owner = acting?.principal ?? await address2();
297294
297637
  const page = await invitesModule.readMyPage(SITE, await inviteSigner(acting));
297295
297638
  if (!page) return text4(`${owner} has no page. Nothing to remove.`);
297296
- const where2 = `${SITE.replace(/\/+$/, "")}/pro/pros/${page.profile.handle}`;
297639
+ const where2 = `${SITE.replace(/\/+$/, "")}/pros/${page.profile.handle}`;
297297
297640
  if (!confirm)
297298
297641
  return text4(
297299
297642
  [