@ixo/asks-mcp 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/asks-mcp.mjs +72 -15
  2. package/package.json +1 -1
package/dist/asks-mcp.mjs CHANGED
@@ -264678,6 +264678,14 @@ function readVetMessage(message, expected, now3 = Date.now(), maxAgeMs = STAFF_P
264678
264678
  if (parts.length !== 6 || parts[0] !== "vet" || parts[1] !== expected.address || parts[2] !== expected.by || parts[3] !== expected.decision || parts[5] !== expected.digest) return "mismatch";
264679
264679
  return fresh(parts[4], now3, maxAgeMs);
264680
264680
  }
264681
+ function readHandsMineMessage(message, expected, now3 = Date.now(), maxAgeMs = READ_PROOF_MAX_AGE_MS) {
264682
+ const parts = message.split(":");
264683
+ if (parts.length !== 3 || parts[0] !== "hands-mine" || parts[1] !== expected.address) return "mismatch";
264684
+ return fresh(parts[2], now3, maxAgeMs);
264685
+ }
264686
+ function readHandsShareMessage(message, expected) {
264687
+ return message === handsShareMessage(expected.address, expected.prefAt, expected.act) ? "ok" : "mismatch";
264688
+ }
264681
264689
  function readHandsRemoveMessage(message, expected) {
264682
264690
  const parts = message.split(":");
264683
264691
  if (parts.length !== 3 || parts[0] !== "hands-remove" || parts[1] !== expected.address) return "mismatch";
@@ -264704,7 +264712,7 @@ async function digestOf(value) {
264704
264712
  const bytes3 = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonicalJson2(value))));
264705
264713
  return Array.from(bytes3, (byte) => byte.toString(16).padStart(2, "0")).join("");
264706
264714
  }
264707
- 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, LINKEDIN_ACTS, linkedinBody, linkedinMessage, ROOM_ACTS, roomBody, roomMessage, ROOM_SEND_MAX_AGE_MS, SPONSOR_ACTS, sponsorBody, sponsorMessage;
264715
+ 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;
264708
264716
  var init_inviteMessages = __esm({
264709
264717
  "../../packages/openhands-sdk/src/chain/inviteMessages.ts"() {
264710
264718
  "use strict";
@@ -264732,6 +264740,7 @@ var init_inviteMessages = __esm({
264732
264740
  vetBody = (body) => ({ decision: body["decision"] ?? null, prefAt: body["prefAt"] ?? null, note: body["note"] ?? null, scope: body["scope"] ?? null });
264733
264741
  vetMessage = (address2, by, decision, now3 = Date.now(), digest2 = "") => `vet:${address2}:${by}:${decision}:${now3}:${digest2}`;
264734
264742
  handsRemoveMessage = (address2, prefAt) => `hands-remove:${address2}:${prefAt}`;
264743
+ handsMineMessage = (address2, now3 = Date.now()) => `hands-mine:${address2}:${now3}`;
264735
264744
  LINKEDIN_ACTS = ["start", "remove"];
264736
264745
  linkedinBody = (body) => {
264737
264746
  const { address: _address, proof: _proof, ...rest } = body;
@@ -264751,6 +264760,8 @@ var init_inviteMessages = __esm({
264751
264760
  return rest;
264752
264761
  };
264753
264762
  sponsorMessage = (act, signer2, now3 = Date.now(), digest2 = "") => `sponsor-${act}:${signer2}:${now3}:${digest2}`;
264763
+ HANDS_SHARE_ACTS = ["create", "replace"];
264764
+ handsShareMessage = (address2, prefAt, act) => `hands-share:${address2}:${prefAt}:${act}`;
264754
264765
  }
264755
264766
  });
264756
264767
 
@@ -264785,6 +264796,7 @@ __export(inviteProof_exports, {
264785
264796
  DOES: () => DOES,
264786
264797
  FUTURE_SKEW_MS: () => FUTURE_SKEW_MS,
264787
264798
  HANDLE: () => HANDLE,
264799
+ HANDS_SHARE_ACTS: () => HANDS_SHARE_ACTS,
264788
264800
  HAND_LIMITS: () => HAND_LIMITS,
264789
264801
  INVITE_ANSWERS: () => INVITE_ANSWERS,
264790
264802
  INVITE_OPS: () => INVITE_OPS,
@@ -264811,7 +264823,9 @@ __export(inviteProof_exports, {
264811
264823
  digestOf: () => digestOf,
264812
264824
  fresh: () => fresh,
264813
264825
  handsMessage: () => handsMessage,
264826
+ handsMineMessage: () => handsMineMessage,
264814
264827
  handsRemoveMessage: () => handsRemoveMessage,
264828
+ handsShareMessage: () => handsShareMessage,
264815
264829
  inviteOpBody: () => inviteOpBody,
264816
264830
  inviteOpMessage: () => inviteOpMessage,
264817
264831
  inviteOpWords: () => inviteOpWords,
@@ -264827,7 +264841,9 @@ __export(inviteProof_exports, {
264827
264841
  readHandBlock: () => readHandBlock,
264828
264842
  readHandProfile: () => readHandProfile,
264829
264843
  readHandsMessage: () => readHandsMessage,
264844
+ readHandsMineMessage: () => readHandsMineMessage,
264830
264845
  readHandsRemoveMessage: () => readHandsRemoveMessage,
264846
+ readHandsShareMessage: () => readHandsShareMessage,
264831
264847
  readInviteOpMessage: () => readInviteOpMessage,
264832
264848
  readInvitedMessage: () => readInvitedMessage,
264833
264849
  readLegacyVetRequestMessage: () => readLegacyVetRequestMessage,
@@ -264890,6 +264906,7 @@ function readHandProfile(raw) {
264890
264906
  if (!AVAILABILITY.includes(availability)) return { problem: `availability is ${AVAILABILITY.join(", ")}` };
264891
264907
  const invitable = it2.invitable === void 0 ? true : it2.invitable;
264892
264908
  if (typeof invitable !== "boolean") return { problem: "invitable is true or false" };
264909
+ if (it2.listed !== void 0 && typeof it2.listed !== "boolean") return { problem: "listed is true or false" };
264893
264910
  const L5 = HAND_LIMITS;
264894
264911
  const pictureUrl = (value, what) => value === void 0 || value === null || value === "" ? void 0 : https3(value) ? value : { problem: `${what} is an https address` };
264895
264912
  const avatar = pictureUrl(it2.avatar, "avatar");
@@ -264967,6 +264984,8 @@ function readHandProfile(raw) {
264967
264984
  links: [...new Set(links)],
264968
264985
  availability,
264969
264986
  invitable,
264987
+ /* Only a private page carries it, so a page signed by an app from before the flag digests the same. */
264988
+ ...it2.listed === false ? { listed: false } : {},
264970
264989
  ...avatar ? { avatar } : {},
264971
264990
  ...banner ? { banner } : {},
264972
264991
  ...location ? { location } : {},
@@ -265142,6 +265161,7 @@ __export(invites_exports, {
265142
265161
  post: () => post,
265143
265162
  rateWords: () => rateWords,
265144
265163
  readInvites: () => readInvites,
265164
+ readMyPage: () => readMyPage,
265145
265165
  readNotices: () => readNotices,
265146
265166
  readPage: () => readPage,
265147
265167
  readStanding: () => readStanding,
@@ -265151,6 +265171,7 @@ __export(invites_exports, {
265151
265171
  rowAnswerWords: () => rowAnswerWords,
265152
265172
  setMarketplacePage: () => setMarketplacePage,
265153
265173
  setPage: () => setPage,
265174
+ sharePage: () => sharePage,
265154
265175
  standingWords: () => standingWords,
265155
265176
  startLinkedin: () => startLinkedin,
265156
265177
  writeInvites: () => writeInvites,
@@ -265395,6 +265416,23 @@ async function readPage(site, which, fetchImpl = fetch) {
265395
265416
  const body = await response.json().catch(() => null);
265396
265417
  return body?.hand ?? null;
265397
265418
  }
265419
+ async function readMyPage(site, signer2, fetchImpl = fetch) {
265420
+ const owner = signer2.principal ?? signer2.address;
265421
+ const message = handsMineMessage(owner);
265422
+ const answer = await post(site, "/api/hands/mine", { address: signer2.address, ...signer2.principal ? { onBehalfOf: signer2.principal } : {}, proof: { kind: "adr36", message, ...await signWords(signer2.mnemonic, message) } }, fetchImpl).catch(() => null);
265423
+ if (answer?.ok) return answer.body.hand ? { ...answer.body.hand, shared: answer.body.shared === true } : null;
265424
+ if (answer?.status === 404 && !codeOf2(answer)) return readPage(site, { address: owner }, fetchImpl);
265425
+ return null;
265426
+ }
265427
+ async function sharePage(site, signer2, act, fetchImpl) {
265428
+ const owner = signer2.principal ?? signer2.address;
265429
+ const prefAt = Date.now();
265430
+ const message = handsShareMessage(owner, prefAt, act);
265431
+ const answer = await post(site, "/api/hands/share", { address: signer2.address, ...signer2.principal ? { onBehalfOf: signer2.principal } : {}, prefAt, act, proof: { kind: "adr36", message, ...await signWords(signer2.mnemonic, message) } }, fetchImpl);
265432
+ if (answer.ok && typeof answer.body.code === "string") return { url: `${proOrigin(site)}/pro/p/${answer.body.code}` };
265433
+ if (answer.status === 404 && !codeOf2(answer)) return { refused: "this site does not make private links yet" };
265434
+ return { refused: refusalOf(answer) };
265435
+ }
265398
265436
  function pageWords(page, site) {
265399
265437
  const p = page.profile;
265400
265438
  const rate = rateWords(p.rate);
@@ -265404,6 +265442,7 @@ function pageWords(page, site) {
265404
265442
  page.linkedin ? `LinkedIn verified since ${page.linkedin.verifiedAt.slice(0, 10)}${page.linkedin.profileUrl ? ` \xB7 ${page.linkedin.profileUrl}` : ""}` : "Not LinkedIn verified yet",
265405
265443
  `Address: ${page.address}${p.location ? ` \xB7 ${p.location}` : ""}${p.timezone ? ` (${p.timezone})` : ""}`,
265406
265444
  `Does: ${p.does.length ? p.does.join(", ") : "not said"} \xB7 Rate: ${rate} \xB7 Availability: ${p.availability} \xB7 Invitable by handle: ${p.invitable ? "yes" : "no"}`,
265445
+ p.listed === false ? "Private: not shown on asks.world or in search; only someone who types the exact handle or address can invite them." : "Public: shown on asks.world, anyone can find it.",
265407
265446
  "Profile claims are supplied by the owner. Check what independent providers signed against your own requirements.",
265408
265447
  ...(p.verificationCredentials ?? []).map((one) => `Signed record cited (not verified): ${one.title} \xB7 ${one.issuerDid} \xB7 ${one.url}`),
265409
265448
  ...(p.verificationServices ?? []).map((one) => `Independent service: ${one.title} \xB7 ${one.claims.join(", ")} \xB7 ${one.price} \xB7 Signed by: ${one.issuerDid} \xB7 Method: ${one.method} \xB7 Qualifications: ${one.qualificationCredentials.join(" ")} \xB7 ${one.serviceUrl}`),
@@ -265444,6 +265483,7 @@ var init_invites = __esm({
265444
265483
  "src/invites.ts"() {
265445
265484
  "use strict";
265446
265485
  init_world();
265486
+ init_networks();
265447
265487
  init_dollars();
265448
265488
  init_accountProof();
265449
265489
  init_inviteProof();
@@ -292299,7 +292339,7 @@ import { randomBytes as randomBytes7 } from "node:crypto";
292299
292339
  // package.json
292300
292340
  var package_default = {
292301
292341
  name: "@ixo/asks-mcp",
292302
- version: "1.10.0",
292342
+ version: "1.11.0",
292303
292343
  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.",
292304
292344
  license: "Apache-2.0",
292305
292345
  repository: {
@@ -292662,7 +292702,7 @@ var TOOLS = {
292662
292702
  },
292663
292703
  set_my_page: {
292664
292704
  title: "Write your pro page",
292665
- description: "Make or change the pro page of the person you act for (or this key's own): the page posters find and invite them by, on pro.asks.world and across asks.world. A handle, a name, a headline, what they do, a rate, links, availability, and whether posters may invite them by handle. Previews by default; call again with confirm: true to sign. For guided setup, follow /pro/mcp.md#create-your-pro-profile on the matching Pro Asks host. Start with connect_linkedin: its verified profile pre-fills the name, headline, LinkedIn link and handle; ask only for what LinkedIn lacks (the work they take, rate, availability, a line about them). This tool reads no site itself, so build the rest from what the person tells you or pastes. Spends nothing.",
292705
+ description: "Make or change the pro page of the person you act for (or this key's own): the page posters find and invite them by, on pro.asks.world and across asks.world. A handle, a name, a headline, what they do, a rate, links, availability, whether posters may invite them by handle, and `listed`: public (the default, anyone can find the page) or private (off asks.world and search; only someone who types the exact handle or address can invite them). Ask once, plainly, which they want. A private page can have a secret link (`share_link`: create, or replace to switch the old one off), said once on confirm. Previews by default; call again with confirm: true to sign. For guided setup, follow /pro/mcp.md#create-your-pro-profile on the matching Pro Asks host. Start with connect_linkedin: its verified profile pre-fills the name, headline, LinkedIn link and handle; ask only for what LinkedIn lacks (the work they take, rate, availability, a line about them). This tool reads no site itself, so build the rest from what the person tells you or pastes. Spends nothing.",
292666
292706
  spends: false,
292667
292707
  hosted: false,
292668
292708
  annotations: { ...acts, idempotentHint: true }
@@ -292676,7 +292716,7 @@ var TOOLS = {
292676
292716
  },
292677
292717
  remove_my_page: {
292678
292718
  title: "Remove your pro page",
292679
- description: "Take down the pro page of the person you act for (or this key's own): the page leaves /hands and the directory, and its @handle is freed for anyone. Invitations already on a call's list and the public record of their work stay. Says what goes by default; call again with confirm: true to sign. Spends nothing.",
292719
+ description: "Delete the pro page of the person you act for (or this key's own), for good: the page, its LinkedIn tick and old checks are deleted, it leaves /hands and the directory, and its @handle is freed for anyone. Invitations already on a call's list and the public record of their work stay. Says what goes by default; call again with confirm: true to sign. Spends nothing.",
292680
292720
  spends: false,
292681
292721
  hosted: false,
292682
292722
  annotations: { ...acts, destructiveHint: true, idempotentHint: true }
@@ -297274,6 +297314,7 @@ The room's page: ${roomPage(SITE, collectionId, page?.profile.handle ?? sent.pro
297274
297314
  links: external_exports.array(external_exports.string().url().max(2048)).max(6).optional(),
297275
297315
  availability: external_exports.enum(["open", "busy", "closed"]).optional(),
297276
297316
  invitable: external_exports.boolean().optional().describe("May posters invite them by handle? Default true."),
297317
+ listed: external_exports.boolean().optional().describe("Public (true) or private (false): a private page is off asks.world, the directory and search, and only someone who types the exact handle or address can invite them. Left out, the page keeps what it says now (public for a new page)."),
297277
297318
  avatar: external_exports.string().max(2048).optional().describe("Their picture: a file on this machine (png, jpg or webp, up to 5 MB) or an https address. Uploaded for them; square works best."),
297278
297319
  banner: external_exports.string().max(2048).optional().describe("A wide picture across the top of the page: a file on this machine or an https address. About 3:1."),
297279
297320
  location: external_exports.string().max(80).optional(),
@@ -297298,9 +297339,13 @@ The room's page: ${roomPage(SITE, collectionId, page?.profile.handle ?? sent.pro
297298
297339
  "set_my_page",
297299
297340
  {
297300
297341
  ...meta3("set_my_page"),
297301
- inputSchema: { page: pageInput, confirm: external_exports.boolean().optional().describe("false (the default) previews; true signs and publishes.") }
297342
+ inputSchema: {
297343
+ page: pageInput,
297344
+ share_link: external_exports.enum(["create", "replace"]).optional().describe(`A private page's secret link: "create" makes one, "replace" makes a new one and switches the old one off. Said once, on confirm.`),
297345
+ confirm: external_exports.boolean().optional().describe("false (the default) previews; true signs and publishes.")
297346
+ }
297302
297347
  },
297303
- async ({ page, confirm }) => {
297348
+ async ({ page, share_link, confirm }) => {
297304
297349
  const { readHandProfile: readHandProfile2 } = await Promise.resolve().then(() => (init_inviteProof(), inviteProof_exports));
297305
297350
  const invitesModule = await Promise.resolve().then(() => (init_invites(), invites_exports));
297306
297351
  if ([page.name, page.headline, page.about, ...page.story ?? [], ...(page.experience ?? []).map((one) => one.what ?? "")].some((one) => one && isTainted(one))) return text4(TAINT_REFUSAL);
@@ -297317,9 +297362,13 @@ The room's page: ${roomPage(SITE, collectionId, page?.profile.handle ?? sent.pro
297317
297362
  }
297318
297363
  const { pictures: _pictures, files, story, ...rest } = page;
297319
297364
  const blocks = [...story?.length ? [{ kind: "story", paragraphs: story }] : [], ...pictures.length ? [{ kind: "pictures", items: pictures }] : [], ...files?.length ? [{ kind: "files", items: files }] : []];
297365
+ const acting = await principal2();
297366
+ const owner = acting?.principal ?? await address2();
297367
+ const listed = page.listed ?? (await invitesModule.readMyPage(SITE, await inviteSigner(acting)).catch(() => null))?.profile.listed ?? true;
297320
297368
  const read9 = readHandProfile2({
297321
297369
  v: 1,
297322
297370
  ...rest,
297371
+ listed,
297323
297372
  does: page.does ?? [],
297324
297373
  links: page.links ?? [],
297325
297374
  availability: page.availability ?? "open",
@@ -297331,28 +297380,36 @@ The room's page: ${roomPage(SITE, collectionId, page?.profile.handle ?? sent.pro
297331
297380
  });
297332
297381
  if ("problem" in read9) return text4(`Not a page yet: ${read9.problem}. Nothing was published.`);
297333
297382
  const pending = [page.avatar, page.banner, ...(page.pictures ?? []).map((one) => one.url)].filter((one) => one && !/^https:\/\//.test(one)).length;
297334
- const acting = await principal2();
297335
- const owner = acting?.principal ?? await address2();
297336
297383
  const preview = invitesModule.pageWords({ address: owner, profile: read9.profile, updated_at: "" }, SITE);
297384
+ const linkWords = share_link ? `
297385
+
297386
+ On confirm, ${share_link === "replace" ? "a new private link is made and the old one stops working" : "a private link is made"}: anyone with it can see the page.` : "";
297337
297387
  if (!confirm) return text4(`This is the page, as the site will show it:
297338
297388
 
297339
- ${preview}${pending ? `
297389
+ ${preview}${linkWords}${pending ? `
297340
297390
 
297341
297391
  ${pending} picture${pending === 1 ? "" : "s"} on this machine will be uploaded when you confirm.` : ""}
297342
297392
 
297343
297393
  Show it to the person. Then call again with confirm: true to sign and publish it${acting ? ` as ${acting.principal}` : " for this key"}.`);
297344
297394
  const answer = await invitesModule.setPage(SITE, await inviteSigner(acting), read9.profile);
297345
297395
  if ("refused" in answer) return text4(`Refused: ${answer.refused}. Nothing changed.`);
297346
- return text4(`Published the profile for ${answer.address}: ${proPage(SITE, answer.handle)}. Also available at ${SITE}/pro/pros/${answer.handle}. Posters invite them with "@${answer.handle}".`);
297396
+ const link5 = share_link ? await invitesModule.sharePage(SITE, await inviteSigner(acting), share_link) : null;
297397
+ const linkLine = !link5 ? "" : "url" in link5 ? `
297398
+
297399
+ Here's your private link: ${link5.url}. Anyone with it can see your page; ask me for a new one to switch the old one off.` : `
297400
+
297401
+ No private link was made: ${link5.refused}.`;
297402
+ if (read9.profile.listed === false) return text4(`Saved the private profile for ${answer.address}. It is not shown on asks.world or in search; posters who type "@${answer.handle}" or the address can still invite them.${linkLine}`);
297403
+ return text4(`Published the profile for ${answer.address}: ${proPage(SITE, answer.handle)}. Also available at ${SITE}/pro/pros/${answer.handle}. Posters invite them with "@${answer.handle}".${linkLine}`);
297347
297404
  }
297348
297405
  );
297349
297406
  if (offered("my_page")) server2.registerTool("my_page", { ...meta3("my_page"), inputSchema: {} }, async () => {
297350
297407
  const invitesModule = await Promise.resolve().then(() => (init_invites(), invites_exports));
297351
297408
  const acting = await principal2();
297352
- const owner = acting?.principal ?? await address2();
297353
- const page = await invitesModule.readPage(SITE, { address: owner });
297409
+ const page = await invitesModule.readMyPage(SITE, await inviteSigner(acting));
297354
297410
  if (!page) return text4("No pro page yet. Next: connect_linkedin (about a minute).");
297355
297411
  return text4(`${invitesModule.pageWords(page, SITE)}
297412
+ ${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).'}
297356
297413
 
297357
297414
  Edit the profile at ${EXPERT_SITE}/pro/profile.${page.linkedin ? "" : " Next: connect_linkedin verifies it, so you can be invited to pro asks."}`);
297358
297415
  });
@@ -297468,7 +297525,7 @@ Show it to the person. Then call again with the same page and confirm: true to s
297468
297525
  if (status.state === "failed") return text4(`Not verified: ${status.error ?? "the LinkedIn login did not finish"}. Next: connect_linkedin with no id gives a new link.`);
297469
297526
  const profile = status.profile;
297470
297527
  const acting = await principal2();
297471
- const page = await invitesModule.readPage(SITE, { address: acting?.principal ?? await address2() });
297528
+ const page = await invitesModule.readMyPage(SITE, await inviteSigner(acting));
297472
297529
  const vanity = (profile?.vanity ?? "").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 30);
297473
297530
  const prefill = {
297474
297531
  ...profile?.name ? { name: profile.name.slice(0, 80) } : {},
@@ -297491,14 +297548,14 @@ ${asData("linkedin", JSON.stringify(prefill, null, 2))}`
297491
297548
  const invitesModule = await Promise.resolve().then(() => (init_invites(), invites_exports));
297492
297549
  const acting = await principal2();
297493
297550
  const owner = acting?.principal ?? await address2();
297494
- const page = await invitesModule.readPage(SITE, { address: owner });
297551
+ const page = await invitesModule.readMyPage(SITE, await inviteSigner(acting));
297495
297552
  if (!page) return text4(`${owner} has no page. Nothing to remove.`);
297496
297553
  const where2 = `${SITE.replace(/\/+$/, "")}/pro/pros/${page.profile.handle}`;
297497
297554
  if (!confirm)
297498
297555
  return text4(
297499
297556
  [
297500
297557
  `This takes down @${page.profile.handle} (${where2}, ${proPage(SITE, page.profile.handle)} on pro.asks.world), the page of ${owner}${acting ? ", the person this key acts for" : ""}:`,
297501
- `- The page and everything on it go: the CV, the rate, the links. It leaves the Hands directory.`,
297558
+ `- The page and everything on it are deleted: the CV, the rate, the links, and the LinkedIn tick (that LinkedIn can verify again later). It leaves the Hands directory. This can't be undone.`,
297502
297559
  `- The handle @${page.profile.handle} is freed, and anybody may take it. Posters can no longer invite them by it.`,
297503
297560
  `- Invitations already on a call's list name the address, and stay. Their work and decisions are the public record and are not touched.`,
297504
297561
  `- Pictures uploaded for the page stay at their IPFS addresses; nothing links to them from the site any more.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ixo/asks-mcp",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "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.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {