@cmo-so/mcp 0.9.1 → 0.9.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/cmo-mcp.mjs +347 -194
  2. package/package.json +1 -1
package/dist/cmo-mcp.mjs CHANGED
@@ -449,9 +449,9 @@ var require_codegen = __commonJS({
449
449
  }
450
450
  };
451
451
  var Label = class extends Node {
452
- constructor(label) {
452
+ constructor(label2) {
453
453
  super();
454
- this.label = label;
454
+ this.label = label2;
455
455
  this.names = {};
456
456
  }
457
457
  render({ _n }) {
@@ -459,14 +459,14 @@ var require_codegen = __commonJS({
459
459
  }
460
460
  };
461
461
  var Break = class extends Node {
462
- constructor(label) {
462
+ constructor(label2) {
463
463
  super();
464
- this.label = label;
464
+ this.label = label2;
465
465
  this.names = {};
466
466
  }
467
467
  render({ _n }) {
468
- const label = this.label ? ` ${this.label}` : "";
469
- return `break${label};` + _n;
468
+ const label2 = this.label ? ` ${this.label}` : "";
469
+ return `break${label2};` + _n;
470
470
  }
471
471
  };
472
472
  var Throw = class extends Node {
@@ -506,17 +506,17 @@ var require_codegen = __commonJS({
506
506
  this.nodes = nodes;
507
507
  }
508
508
  render(opts) {
509
- return this.nodes.reduce((code, n) => code + n.render(opts), "");
509
+ return this.nodes.reduce((code, n2) => code + n2.render(opts), "");
510
510
  }
511
511
  optimizeNodes() {
512
512
  const { nodes } = this;
513
513
  let i = nodes.length;
514
514
  while (i--) {
515
- const n = nodes[i].optimizeNodes();
516
- if (Array.isArray(n))
517
- nodes.splice(i, 1, ...n);
518
- else if (n)
519
- nodes[i] = n;
515
+ const n2 = nodes[i].optimizeNodes();
516
+ if (Array.isArray(n2))
517
+ nodes.splice(i, 1, ...n2);
518
+ else if (n2)
519
+ nodes[i] = n2;
520
520
  else
521
521
  nodes.splice(i, 1);
522
522
  }
@@ -526,16 +526,16 @@ var require_codegen = __commonJS({
526
526
  const { nodes } = this;
527
527
  let i = nodes.length;
528
528
  while (i--) {
529
- const n = nodes[i];
530
- if (n.optimizeNames(names, constants))
529
+ const n2 = nodes[i];
530
+ if (n2.optimizeNames(names, constants))
531
531
  continue;
532
- subtractNames(names, n.names);
532
+ subtractNames(names, n2.names);
533
533
  nodes.splice(i, 1);
534
534
  }
535
535
  return nodes.length > 0 ? this : void 0;
536
536
  }
537
537
  get names() {
538
- return this.nodes.reduce((names, n) => addNames(names, n.names), {});
538
+ return this.nodes.reduce((names, n2) => addNames(names, n2.names), {});
539
539
  }
540
540
  };
541
541
  var BlockNode = class extends ParentNode {
@@ -878,12 +878,12 @@ var require_codegen = __commonJS({
878
878
  return this._endBlockNode(For);
879
879
  }
880
880
  // `label` statement
881
- label(label) {
882
- return this._leafNode(new Label(label));
881
+ label(label2) {
882
+ return this._leafNode(new Label(label2));
883
883
  }
884
884
  // `break` statement
885
- break(label) {
886
- return this._leafNode(new Break(label));
885
+ break(label2) {
886
+ return this._leafNode(new Break(label2));
887
887
  }
888
888
  // `return` statement
889
889
  return(value) {
@@ -946,8 +946,8 @@ var require_codegen = __commonJS({
946
946
  endFunc() {
947
947
  return this._endBlockNode(Func);
948
948
  }
949
- optimize(n = 1) {
950
- while (n-- > 0) {
949
+ optimize(n2 = 1) {
950
+ while (n2-- > 0) {
951
951
  this._root.optimizeNodes();
952
952
  this._root.optimizeNames(this._root.names, this._constants);
953
953
  }
@@ -961,19 +961,19 @@ var require_codegen = __commonJS({
961
961
  this._nodes.push(node2);
962
962
  }
963
963
  _endBlockNode(N1, N2) {
964
- const n = this._currNode;
965
- if (n instanceof N1 || N2 && n instanceof N2) {
964
+ const n2 = this._currNode;
965
+ if (n2 instanceof N1 || N2 && n2 instanceof N2) {
966
966
  this._nodes.pop();
967
967
  return this;
968
968
  }
969
969
  throw new Error(`CodeGen: not in block "${N2 ? `${N1.kind}/${N2.kind}` : N1.kind}"`);
970
970
  }
971
971
  _elseNode(node2) {
972
- const n = this._currNode;
973
- if (!(n instanceof If)) {
972
+ const n2 = this._currNode;
973
+ if (!(n2 instanceof If)) {
974
974
  throw new Error('CodeGen: "else" without "if"');
975
975
  }
976
- this._currNode = n.else = node2;
976
+ this._currNode = n2.else = node2;
977
977
  return this;
978
978
  }
979
979
  get _root() {
@@ -990,8 +990,8 @@ var require_codegen = __commonJS({
990
990
  };
991
991
  exports.CodeGen = CodeGen;
992
992
  function addNames(names, from) {
993
- for (const n in from)
994
- names[n] = (names[n] || 0) + (from[n] || 0);
993
+ for (const n2 in from)
994
+ names[n2] = (names[n2] || 0) + (from[n2] || 0);
995
995
  return names;
996
996
  }
997
997
  function addExprNames(names, from) {
@@ -1002,20 +1002,20 @@ var require_codegen = __commonJS({
1002
1002
  return replaceName(expr);
1003
1003
  if (!canOptimize(expr))
1004
1004
  return expr;
1005
- return new code_1._Code(expr._items.reduce((items, c) => {
1005
+ return new code_1._Code(expr._items.reduce((items2, c) => {
1006
1006
  if (c instanceof code_1.Name)
1007
1007
  c = replaceName(c);
1008
1008
  if (c instanceof code_1._Code)
1009
- items.push(...c._items);
1009
+ items2.push(...c._items);
1010
1010
  else
1011
- items.push(c);
1012
- return items;
1011
+ items2.push(c);
1012
+ return items2;
1013
1013
  }, []));
1014
- function replaceName(n) {
1015
- const c = constants[n.str];
1016
- if (c === void 0 || names[n.str] !== 1)
1017
- return n;
1018
- delete names[n.str];
1014
+ function replaceName(n2) {
1015
+ const c = constants[n2.str];
1016
+ if (c === void 0 || names[n2.str] !== 1)
1017
+ return n2;
1018
+ delete names[n2.str];
1019
1019
  return c;
1020
1020
  }
1021
1021
  function canOptimize(e) {
@@ -1023,8 +1023,8 @@ var require_codegen = __commonJS({
1023
1023
  }
1024
1024
  }
1025
1025
  function subtractNames(names, from) {
1026
- for (const n in from)
1027
- names[n] = (names[n] || 0) - (from[n] || 0);
1026
+ for (const n2 in from)
1027
+ names[n2] = (names[n2] || 0) - (from[n2] || 0);
1028
1028
  }
1029
1029
  function not(x) {
1030
1030
  return typeof x == "boolean" || typeof x == "number" || x === null ? !x : (0, code_1._)`!${par(x)}`;
@@ -1167,7 +1167,7 @@ var require_util = __commonJS({
1167
1167
  mergeNames: (gen, from, to) => gen.if((0, codegen_1._)`${to} !== true && ${from} !== undefined`, () => gen.assign(to, (0, codegen_1._)`${from} === true ? true : ${to} > ${from} ? ${to} : ${from}`)),
1168
1168
  mergeToName: (gen, from, to) => gen.if((0, codegen_1._)`${to} !== true`, () => gen.assign(to, from === true ? true : (0, codegen_1._)`${to} > ${from} ? ${to} : ${from}`)),
1169
1169
  mergeValues: (from, to) => from === true ? true : Math.max(from, to),
1170
- resultToName: (gen, items) => gen.var("items", items)
1170
+ resultToName: (gen, items2) => gen.var("items", items2)
1171
1171
  })
1172
1172
  };
1173
1173
  function evaluatedPropsToName(gen, ps) {
@@ -1361,12 +1361,12 @@ var require_errors = __commonJS({
1361
1361
  }
1362
1362
  return [E.schemaPath, schPath];
1363
1363
  }
1364
- function extraErrorProps(cxt, { params, message }, keyValues) {
1364
+ function extraErrorProps(cxt, { params, message: message2 }, keyValues) {
1365
1365
  const { keyword, data, schemaValue, it } = cxt;
1366
1366
  const { opts, propertyName, topSchemaRef, schemaPath } = it;
1367
1367
  keyValues.push([E.keyword, keyword], [E.params, typeof params == "function" ? params(cxt) : params || (0, codegen_1._)`{}`]);
1368
1368
  if (opts.messages) {
1369
- keyValues.push([E.message, typeof message == "function" ? message(cxt) : message]);
1369
+ keyValues.push([E.message, typeof message2 == "function" ? message2(cxt) : message2]);
1370
1370
  }
1371
1371
  if (opts.verbose) {
1372
1372
  keyValues.push([E.schema, schemaValue], [E.parentSchema, (0, codegen_1._)`${topSchemaRef}${schemaPath}`], [names_1.default.data, data]);
@@ -1675,13 +1675,13 @@ var require_defaults = __commonJS({
1675
1675
  var codegen_1 = require_codegen();
1676
1676
  var util_1 = require_util();
1677
1677
  function assignDefaults(it, ty) {
1678
- const { properties, items } = it.schema;
1678
+ const { properties, items: items2 } = it.schema;
1679
1679
  if (ty === "object" && properties) {
1680
1680
  for (const key in properties) {
1681
1681
  assignDefault(it, key, properties[key].default);
1682
1682
  }
1683
- } else if (ty === "array" && Array.isArray(items)) {
1684
- items.forEach((sch, i) => assignDefault(it, i, sch.default));
1683
+ } else if (ty === "array" && Array.isArray(items2)) {
1684
+ items2.forEach((sch, i) => assignDefault(it, i, sch.default));
1685
1685
  }
1686
1686
  }
1687
1687
  exports.assignDefaults = assignDefaults;
@@ -2485,11 +2485,11 @@ var require_validate = __commonJS({
2485
2485
  gen.return((0, codegen_1._)`${names_1.default.errors} === 0`);
2486
2486
  }
2487
2487
  }
2488
- function assignEvaluated({ gen, evaluated, props, items }) {
2488
+ function assignEvaluated({ gen, evaluated, props, items: items2 }) {
2489
2489
  if (props instanceof codegen_1.Name)
2490
2490
  gen.assign((0, codegen_1._)`${evaluated}.props`, props);
2491
- if (items instanceof codegen_1.Name)
2492
- gen.assign((0, codegen_1._)`${evaluated}.items`, items);
2491
+ if (items2 instanceof codegen_1.Name)
2492
+ gen.assign((0, codegen_1._)`${evaluated}.items`, items2);
2493
2493
  }
2494
2494
  function schemaKeywords(it, types, typeErrors, errsCount) {
2495
2495
  const { gen, schema, data, allErrors, opts, self } = it;
@@ -2952,12 +2952,12 @@ var require_compile = __commonJS({
2952
2952
  validate2.source = { validateName, validateCode, scopeValues: gen._values };
2953
2953
  }
2954
2954
  if (this.opts.unevaluated) {
2955
- const { props, items } = schemaCxt;
2955
+ const { props, items: items2 } = schemaCxt;
2956
2956
  validate2.evaluated = {
2957
2957
  props: props instanceof codegen_1.Name ? void 0 : props,
2958
- items: items instanceof codegen_1.Name ? void 0 : items,
2958
+ items: items2 instanceof codegen_1.Name ? void 0 : items2,
2959
2959
  dynamicProps: props instanceof codegen_1.Name,
2960
- dynamicItems: items instanceof codegen_1.Name
2960
+ dynamicItems: items2 instanceof codegen_1.Name
2961
2961
  };
2962
2962
  if (validate2.source)
2963
2963
  validate2.source.evaluated = (0, codegen_1.stringify)(validate2.evaluated);
@@ -4496,11 +4496,11 @@ var require_core = __commonJS({
4496
4496
  }
4497
4497
  const valid = this.validate($schema, schema);
4498
4498
  if (!valid && throwOrLogError) {
4499
- const message = "schema is invalid: " + this.errorsText();
4499
+ const message2 = "schema is invalid: " + this.errorsText();
4500
4500
  if (this.opts.validateSchema === "log")
4501
- this.logger.error(message);
4501
+ this.logger.error(message2);
4502
4502
  else
4503
- throw new Error(message);
4503
+ throw new Error(message2);
4504
4504
  }
4505
4505
  return valid;
4506
4506
  }
@@ -4967,8 +4967,8 @@ var require_ref = __commonJS({
4967
4967
  it.items = util_1.mergeEvaluated.items(gen, schEvaluated.items, it.items);
4968
4968
  }
4969
4969
  } else {
4970
- const items = gen.var("items", (0, codegen_1._)`${source}.evaluated.items`);
4971
- it.items = util_1.mergeEvaluated.items(gen, items, it.items, codegen_1.Name);
4970
+ const items2 = gen.var("items", (0, codegen_1._)`${source}.evaluated.items`);
4971
+ it.items = util_1.mergeEvaluated.items(gen, items2, it.items, codegen_1.Name);
4972
4972
  }
4973
4973
  }
4974
4974
  }
@@ -5508,28 +5508,28 @@ var require_additionalItems = __commonJS({
5508
5508
  error: error2,
5509
5509
  code(cxt) {
5510
5510
  const { parentSchema, it } = cxt;
5511
- const { items } = parentSchema;
5512
- if (!Array.isArray(items)) {
5511
+ const { items: items2 } = parentSchema;
5512
+ if (!Array.isArray(items2)) {
5513
5513
  (0, util_1.checkStrictMode)(it, '"additionalItems" is ignored when "items" is not an array of schemas');
5514
5514
  return;
5515
5515
  }
5516
- validateAdditionalItems(cxt, items);
5516
+ validateAdditionalItems(cxt, items2);
5517
5517
  }
5518
5518
  };
5519
- function validateAdditionalItems(cxt, items) {
5519
+ function validateAdditionalItems(cxt, items2) {
5520
5520
  const { gen, schema, data, keyword, it } = cxt;
5521
5521
  it.items = true;
5522
5522
  const len = gen.const("len", (0, codegen_1._)`${data}.length`);
5523
5523
  if (schema === false) {
5524
- cxt.setParams({ len: items.length });
5525
- cxt.pass((0, codegen_1._)`${len} <= ${items.length}`);
5524
+ cxt.setParams({ len: items2.length });
5525
+ cxt.pass((0, codegen_1._)`${len} <= ${items2.length}`);
5526
5526
  } else if (typeof schema == "object" && !(0, util_1.alwaysValidSchema)(it, schema)) {
5527
- const valid = gen.var("valid", (0, codegen_1._)`${len} <= ${items.length}`);
5527
+ const valid = gen.var("valid", (0, codegen_1._)`${len} <= ${items2.length}`);
5528
5528
  gen.if((0, codegen_1.not)(valid), () => validateItems(valid));
5529
5529
  cxt.ok(valid);
5530
5530
  }
5531
5531
  function validateItems(valid) {
5532
- gen.forRange("i", items.length, len, (i) => {
5532
+ gen.forRange("i", items2.length, len, (i) => {
5533
5533
  cxt.subschema({ keyword, dataProp: i, dataPropType: util_1.Type.Num }, valid);
5534
5534
  if (!it.allErrors)
5535
5535
  gen.if((0, codegen_1.not)(valid), () => gen.break());
@@ -7199,7 +7199,7 @@ var require_dist = __commonJS({
7199
7199
  // package.json
7200
7200
  var package_default = {
7201
7201
  name: "@cmo-so/cli",
7202
- version: "0.9.1",
7202
+ version: "0.9.3",
7203
7203
  description: "CMO.so on the command line: your websites, ideas, blog posts, LinkedIn queue and results, plus a local MCP server for Claude Desktop, Cursor and other MCP clients.",
7204
7204
  type: "module",
7205
7205
  license: "MIT",
@@ -7271,14 +7271,14 @@ var OAuthError = class extends Error {
7271
7271
  }
7272
7272
  };
7273
7273
  var SignInRequiredError = class extends Error {
7274
- constructor(message = "Please sign in again.") {
7275
- super(message);
7274
+ constructor(message2 = "Please sign in again.") {
7275
+ super(message2);
7276
7276
  this.name = "SignInRequiredError";
7277
7277
  }
7278
7278
  };
7279
7279
  var ApiError = class extends Error {
7280
- constructor(status, message, requestId, detail = null) {
7281
- super(message);
7280
+ constructor(status, message2, requestId, detail = null) {
7281
+ super(message2);
7282
7282
  this.status = status;
7283
7283
  this.requestId = requestId;
7284
7284
  this.detail = detail;
@@ -7508,10 +7508,10 @@ function createApi({ baseUrl, session: session2, fetch: fetchImpl = globalThis.f
7508
7508
  }),
7509
7509
  models: () => request("/v1/maggie/bridge/models"),
7510
7510
  /** Add a ChatGPT account to the bridge (then connect it). */
7511
- addAccount: (label) => request("/v1/maggie/bridge/accounts", {
7511
+ addAccount: (label2) => request("/v1/maggie/bridge/accounts", {
7512
7512
  method: "POST",
7513
7513
  headers: { "Content-Type": "application/json" },
7514
- body: JSON.stringify({ label: label ?? null })
7514
+ body: JSON.stringify({ label: label2 ?? null })
7515
7515
  }),
7516
7516
  /** Make one of the bridge's ChatGPT accounts the one that answers. */
7517
7517
  chooseAccount: (id) => request(`/v1/maggie/bridge/accounts/${encodeURIComponent(id)}/use`, { method: "POST" }),
@@ -7530,8 +7530,8 @@ function createApi({ baseUrl, session: session2, fetch: fetchImpl = globalThis.f
7530
7530
  /** The user has read the team's latest reply or status change. */
7531
7531
  seen: (id) => request(`/v1/feedback/${encodeURIComponent(id)}/seen`, { method: "POST" }),
7532
7532
  /** One of the user's feedback photos as a data: URL (an <Image> source on web and native). */
7533
- photo: async (id, n) => {
7534
- const { type, bytes } = await requestBytes(`/v1/feedback/${encodeURIComponent(id)}/photos/${n}`);
7533
+ photo: async (id, n2) => {
7534
+ const { type, bytes } = await requestBytes(`/v1/feedback/${encodeURIComponent(id)}/photos/${n2}`);
7535
7535
  return dataUrl(type, bytes);
7536
7536
  }
7537
7537
  },
@@ -7581,8 +7581,8 @@ function errorMessage(data, status) {
7581
7581
  const detail = data?.detail;
7582
7582
  if (typeof detail === "string" && detail) return detail;
7583
7583
  if (detail && typeof detail === "object" && !Array.isArray(detail)) {
7584
- const message = detail.message;
7585
- if (typeof message === "string" && message) return message;
7584
+ const message2 = detail.message;
7585
+ if (typeof message2 === "string" && message2) return message2;
7586
7586
  }
7587
7587
  if (Array.isArray(detail)) {
7588
7588
  const first = detail[0];
@@ -7600,8 +7600,8 @@ function dataUrl(type, bytes) {
7600
7600
  const parts = [];
7601
7601
  let chunk = "";
7602
7602
  for (let i = 0; i < b.length; i += 3) {
7603
- const n = (b[i] ?? 0) << 16 | (b[i + 1] ?? 0) << 8 | (b[i + 2] ?? 0);
7604
- chunk += B64.charAt(n >> 18 & 63) + B64.charAt(n >> 12 & 63) + (i + 1 < b.length ? B64.charAt(n >> 6 & 63) : "=") + (i + 2 < b.length ? B64.charAt(n & 63) : "=");
7603
+ const n2 = (b[i] ?? 0) << 16 | (b[i + 1] ?? 0) << 8 | (b[i + 2] ?? 0);
7604
+ chunk += B64.charAt(n2 >> 18 & 63) + B64.charAt(n2 >> 12 & 63) + (i + 1 < b.length ? B64.charAt(n2 >> 6 & 63) : "=") + (i + 2 < b.length ? B64.charAt(n2 & 63) : "=");
7605
7605
  if (chunk.length >= 8192) {
7606
7606
  parts.push(chunk);
7607
7607
  chunk = "";
@@ -7784,8 +7784,14 @@ function domainApi(api2, domain) {
7784
7784
  /** How a posted Instagram post is doing (read from Instagram, kept 15 minutes; `refresh` reads again). */
7785
7785
  socialInsights: (id, refresh = false) => api2.request(`${base}/social/${id}/insights${refresh ? "?refresh=true" : ""}`),
7786
7786
  deletePostedSocial: (id) => api2.request(`${base}/social/${id}/published`, { method: "DELETE" }),
7787
- /** Change a posted LinkedIn post and put it up again: the old one comes down, the new text goes out now. */
7788
- republishSocial: (id, socialCopy) => post(`${base}/social/${id}/republish`, socialCopy ? { social_copy: socialCopy } : {}),
7787
+ /**
7788
+ * Change a posted post. LinkedIn changes its text in place (likes and comments stay); with `repost`, and on
7789
+ * the other channels, the old one comes down and the new text goes out now.
7790
+ */
7791
+ republishSocial: (id, socialCopy, repost = false) => post(`${base}/social/${id}/republish`, {
7792
+ ...socialCopy ? { social_copy: socialCopy } : {},
7793
+ ...repost ? { repost: true } : {}
7794
+ }),
7789
7795
  restoreSocial: (id) => post(`${base}/social/${id}/restore`),
7790
7796
  pauseSocial: () => post(`${base}/social/pause`),
7791
7797
  /**
@@ -8463,8 +8469,8 @@ function cleanSitemap(entry, domain) {
8463
8469
  if (!url) return "The sitemap must be a web address starting with http:// or https://.";
8464
8470
  let owner = SITEMAP_OWNERS.includes(entry.owner) ? entry.owner : "other";
8465
8471
  if (owner === "own" && domain && !onWebsite(url, domain)) owner = "other";
8466
- const label = (entry.label ?? "").trim().slice(0, SITEMAP_LABEL_MAX);
8467
- const out = { ...entry, url, owner, label: label || null, uses: sitemapUses(owner, entry.uses) };
8472
+ const label2 = (entry.label ?? "").trim().slice(0, SITEMAP_LABEL_MAX);
8473
+ const out = { ...entry, url, owner, label: label2 || null, uses: sitemapUses(owner, entry.uses) };
8468
8474
  if (!out.id) delete out.id;
8469
8475
  return out;
8470
8476
  }
@@ -8481,8 +8487,8 @@ function checkSitemaps(list2) {
8481
8487
  function sitemapCheckLine(check) {
8482
8488
  if (!check || check.status === "unchecked") return "Checked when you save";
8483
8489
  if (check.status === "error") return check.error?.trim() || "Couldn't read this sitemap.";
8484
- const n = check.url_count;
8485
- const found = n == null ? "Read" : `Found ${n.toLocaleString("en-GB")} ${n === 1 ? "page" : "pages"}`;
8490
+ const n2 = check.url_count;
8491
+ const found = n2 == null ? "Read" : `Found ${n2.toLocaleString("en-GB")} ${n2 === 1 ? "page" : "pages"}`;
8486
8492
  const at = check.checked_at ? new Date(check.checked_at) : null;
8487
8493
  const when = at && !Number.isNaN(at.getTime()) ? at.toLocaleDateString("en-GB", { day: "numeric", month: "short", year: "numeric" }) : null;
8488
8494
  return when ? `${found} \xB7 checked ${when}` : found;
@@ -8510,13 +8516,13 @@ var named = (title, id) => {
8510
8516
  const s = String(id ?? "").trim();
8511
8517
  return s && s.length <= 8 ? ` #${s}` : "";
8512
8518
  };
8513
- var list = (xs, n = 5) => {
8519
+ var list = (xs, n2 = 5) => {
8514
8520
  const a = (Array.isArray(xs) ? xs : xs == null ? [] : [xs]).map(String);
8515
- return a.length > n ? `${a.slice(0, n).join(", ")} +${a.length - n}` : a.join(", ");
8521
+ return a.length > n2 ? `${a.slice(0, n2).join(", ")} +${a.length - n2}` : a.join(", ");
8516
8522
  };
8517
- var placeEn = (p, items = "posts") => {
8523
+ var placeEn = (p, items2 = "posts") => {
8518
8524
  const t = String(p ?? "").trim().toLowerCase();
8519
- if (t === "end") return `at the end of the queue, after the ${items} already waiting`;
8525
+ if (t === "end") return `at the end of the queue, after the ${items2} already waiting`;
8520
8526
  if (t === "random") return "at a random place in the queue";
8521
8527
  if (/^\d+$/.test(t)) return Number(t) === 0 ? null : `after the first ${t} in the queue`;
8522
8528
  return null;
@@ -8607,13 +8613,13 @@ var confirmCopy = {
8607
8613
  sitemap_upsert: {
8608
8614
  en: (a) => {
8609
8615
  const whose = { own: "your site's ", competitor: "a competitor's ", other: "another site's " }[a.owner];
8610
- const label = a.label ? ` (${q(a.label)})` : "";
8611
- return a.url ? `Save ${whose ?? "the "}sitemap ${a.url}${label}.` : `Change the sitemap${label}: ${keys(a).filter((k) => k !== "id").join(", ")}.`;
8616
+ const label2 = a.label ? ` (${q(a.label)})` : "";
8617
+ return a.url ? `Save ${whose ?? "the "}sitemap ${a.url}${label2}.` : `Change the sitemap${label2}: ${keys(a).filter((k) => k !== "id").join(", ")}.`;
8612
8618
  },
8613
8619
  "zh-Hant": (a) => {
8614
8620
  const whose = { own: "\u81EA\u5DF1\u7DB2\u7AD9\u7684", competitor: "\u7AF6\u722D\u5C0D\u624B\u7684", other: "\u5176\u4ED6\u7DB2\u7AD9\u7684" }[a.owner];
8615
- const label = a.label ? `\uFF08${q(a.label)}\uFF09` : "";
8616
- return a.url ? `\u5132\u5B58${whose ?? ""} sitemap ${a.url}${label}\u3002` : `\u4FEE\u6539 sitemap${label}\uFF1A${keys(a).filter((k) => k !== "id").join("\u3001")}\u3002`;
8621
+ const label2 = a.label ? `\uFF08${q(a.label)}\uFF09` : "";
8622
+ return a.url ? `\u5132\u5B58${whose ?? ""} sitemap ${a.url}${label2}\u3002` : `\u4FEE\u6539 sitemap${label2}\uFF1A${keys(a).filter((k) => k !== "id").join("\u3001")}\u3002`;
8617
8623
  }
8618
8624
  },
8619
8625
  sitemap_remove: {
@@ -8771,20 +8777,32 @@ var confirmCopy = {
8771
8777
  },
8772
8778
  social_approve: {
8773
8779
  en: (a) => {
8774
- const n = ids(a);
8780
+ const n2 = ids(a);
8775
8781
  const at = placeEn(a.position);
8776
8782
  if (at)
8777
- return `Approve ${n.length > 1 ? `${n.length} posts: ${n.map((i) => `#${i}`).join(", ")}` : `post #${n[0]}`}. ${n.length > 1 ? "They are" : "It is"} queued ${at}, and go${n.length > 1 ? "" : "es"} out where your network can see ${n.length > 1 ? "them" : "it"}.`;
8778
- return n.length > 1 ? `Approve ${n.length} posts: ${n.map((i) => `#${i}`).join(", ")}. Each goes out at your next posting times, where your network can see it.` : `Approve post #${n[0]}. It goes out at your next posting time, where your network can see it.`;
8783
+ return `Approve ${n2.length > 1 ? `${n2.length} posts: ${n2.map((i) => `#${i}`).join(", ")}` : `post #${n2[0]}`}. ${n2.length > 1 ? "They are" : "It is"} queued ${at}, and go${n2.length > 1 ? "" : "es"} out where your network can see ${n2.length > 1 ? "them" : "it"}.`;
8784
+ return n2.length > 1 ? `Approve ${n2.length} posts: ${n2.map((i) => `#${i}`).join(", ")}. Each goes out at your next posting times, where your network can see it.` : `Approve post #${n2[0]}. It goes out at your next posting time, where your network can see it.`;
8779
8785
  },
8780
8786
  "zh-Hant": (a) => {
8781
- const n = ids(a);
8787
+ const n2 = ids(a);
8782
8788
  const at = placeZh(a.position);
8783
8789
  if (at)
8784
- return `\u6279\u51C6${n.length > 1 ? ` ${n.length} \u7BC7\u8CBC\u6587\uFF1A${n.map((i) => `#${i}`).join("\u3001")}` : `\u8CBC\u6587 #${n[0]}`}\u3002${at}\uFF0C\u767C\u51FA\u5F8C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002`;
8785
- return n.length > 1 ? `\u6279\u51C6 ${n.length} \u7BC7\u8CBC\u6587\uFF1A${n.map((i) => `#${i}`).join("\u3001")}\u3002\u6BCF\u7BC7\u5728\u63A5\u4E0B\u4F86\u7684\u767C\u6587\u6642\u9593\u767C\u51FA\uFF0C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002` : `\u6279\u51C6\u8CBC\u6587 #${n[0]}\u3002\u5B83\u6703\u5728\u4E0B\u4E00\u500B\u767C\u6587\u6642\u9593\u767C\u51FA\uFF0C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002`;
8790
+ return `\u6279\u51C6${n2.length > 1 ? ` ${n2.length} \u7BC7\u8CBC\u6587\uFF1A${n2.map((i) => `#${i}`).join("\u3001")}` : `\u8CBC\u6587 #${n2[0]}`}\u3002${at}\uFF0C\u767C\u51FA\u5F8C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002`;
8791
+ return n2.length > 1 ? `\u6279\u51C6 ${n2.length} \u7BC7\u8CBC\u6587\uFF1A${n2.map((i) => `#${i}`).join("\u3001")}\u3002\u6BCF\u7BC7\u5728\u63A5\u4E0B\u4F86\u7684\u767C\u6587\u6642\u9593\u767C\u51FA\uFF0C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002` : `\u6279\u51C6\u8CBC\u6587 #${n2[0]}\u3002\u5B83\u6703\u5728\u4E0B\u4E00\u500B\u767C\u6587\u6642\u9593\u767C\u51FA\uFF0C\u4F60\u7684\u4EBA\u8108\u90FD\u770B\u5F97\u5230\u3002`;
8786
8792
  }
8787
8793
  },
8794
+ social_publish_now: {
8795
+ en: (a) => `Post #${a.id} on its channel now, not at its posting time (even while posting is paused). Everyone who follows you can see it.`,
8796
+ "zh-Hant": (a) => `\u7ACB\u5373\u5728\u5B83\u7684\u983B\u9053\u767C\u51FA\u8CBC\u6587 #${a.id}\uFF0C\u4E0D\u7B49\u767C\u6587\u6642\u9593\uFF08\u66AB\u505C\u767C\u6587\u6642\u4E5F\u6703\u767C\uFF09\u3002\u767C\u51FA\u5F8C\u95DC\u6CE8\u4F60\u7684\u4EBA\u90FD\u770B\u5F97\u5230\u3002`
8797
+ },
8798
+ social_posted_update: {
8799
+ en: (a) => a.repost ? `Take post #${a.id} down (its likes and comments go) and put it up again${a.social_copy ? ` as ${q(a.social_copy)}` : ""}.` : `Change the text of the posted post #${a.id} to ${q(a.social_copy)}. On LinkedIn it stays up with its likes and comments; on other channels it comes down and goes out again.`,
8800
+ "zh-Hant": (a) => a.repost ? `\u64A4\u4E0B\u8CBC\u6587 #${a.id}\uFF08\u8B9A\u548C\u7559\u8A00\u6703\u6D88\u5931\uFF09\uFF0C\u518D\u91CD\u65B0\u767C\u51FA${a.social_copy ? `\uFF0C\u5167\u5BB9\u6539\u70BA ${q(a.social_copy)}` : ""}\u3002` : `\u628A\u5DF2\u767C\u51FA\u7684\u8CBC\u6587 #${a.id} \u6539\u70BA ${q(a.social_copy)}\u3002LinkedIn \u4E0A\u539F\u5730\u4FEE\u6539\uFF0C\u8B9A\u548C\u7559\u8A00\u4FDD\u7559\uFF1B\u5176\u4ED6\u983B\u9053\u6703\u64A4\u4E0B\u5F8C\u91CD\u767C\u3002`
8801
+ },
8802
+ social_posted_delete: {
8803
+ en: (a) => `Take post #${a.id} down from its channel, with its likes and comments. This can't be undone.`,
8804
+ "zh-Hant": (a) => `\u628A\u8CBC\u6587 #${a.id} \u5F9E\u5B83\u7684\u983B\u9053\u64A4\u4E0B\uFF0C\u8B9A\u548C\u7559\u8A00\u4E00\u8D77\u522A\u9664\uFF0C\u7121\u6CD5\u5FA9\u539F\u3002`
8805
+ },
8788
8806
  social_skip: { en: (a) => `Skip post #${a.id}.`, "zh-Hant": (a) => `\u8DF3\u904E\u8CBC\u6587 #${a.id}\u3002` },
8789
8807
  social_restore: {
8790
8808
  en: (a) => `Bring back post #${a.id}.`,
@@ -8838,12 +8856,12 @@ var confirmCopy = {
8838
8856
  },
8839
8857
  social_pictures_attach: {
8840
8858
  en: (a) => {
8841
- const n = (Array.isArray(a.urls) ? a.urls.length : 0) + (Array.isArray(a.files) ? a.files.length : 0);
8842
- return `${a.append ? "Add" : "Put"} your ${n} picture${n === 1 ? "" : "s"} ${a.append ? "after the pictures on" : "on"} post #${a.id}${a.append ? "" : ", in place of its picture"} (free). On LinkedIn a set goes out as a swipeable PDF carousel.`;
8859
+ const n2 = (Array.isArray(a.urls) ? a.urls.length : 0) + (Array.isArray(a.files) ? a.files.length : 0);
8860
+ return `${a.append ? "Add" : "Put"} your ${n2} picture${n2 === 1 ? "" : "s"} ${a.append ? "after the pictures on" : "on"} post #${a.id}${a.append ? "" : ", in place of its picture"} (free). On LinkedIn a set goes out as a swipeable PDF carousel.`;
8843
8861
  },
8844
8862
  "zh-Hant": (a) => {
8845
- const n = (Array.isArray(a.urls) ? a.urls.length : 0) + (Array.isArray(a.files) ? a.files.length : 0);
8846
- return `${a.append ? `\u5728\u8CBC\u6587 #${a.id} \u73FE\u6709\u5716\u7247\u5F8C\u52A0\u4E0A` : `\u628A\u8CBC\u6587 #${a.id} \u7684\u5716\u7247\u63DB\u6210`}\u4F60\u7684 ${n} \u5F35\u5716\u7247\uFF08\u514D\u8CBB\uFF09\u3002\u5728 LinkedIn \u4E0A\uFF0C\u4E00\u7D44\u5716\u7247\u6703\u4EE5\u53EF\u6ED1\u52D5\u7684 PDF \u8F2A\u64AD\u767C\u51FA\u3002`;
8863
+ const n2 = (Array.isArray(a.urls) ? a.urls.length : 0) + (Array.isArray(a.files) ? a.files.length : 0);
8864
+ return `${a.append ? `\u5728\u8CBC\u6587 #${a.id} \u73FE\u6709\u5716\u7247\u5F8C\u52A0\u4E0A` : `\u628A\u8CBC\u6587 #${a.id} \u7684\u5716\u7247\u63DB\u6210`}\u4F60\u7684 ${n2} \u5F35\u5716\u7247\uFF08\u514D\u8CBB\uFF09\u3002\u5728 LinkedIn \u4E0A\uFF0C\u4E00\u7D44\u5716\u7247\u6703\u4EE5\u53EF\u6ED1\u52D5\u7684 PDF \u8F2A\u64AD\u767C\u51FA\u3002`;
8847
8865
  }
8848
8866
  },
8849
8867
  social_carousel_pdf_attach: {
@@ -9072,35 +9090,104 @@ function confirmText(tool2, args, lang = "en") {
9072
9090
  function costText(cost, lang = "en") {
9073
9091
  const parts = [];
9074
9092
  if (cost.aiGenerations) {
9075
- const n = cost.aiGenerations;
9093
+ const n2 = cost.aiGenerations;
9076
9094
  const left = cost.aiLeft;
9077
9095
  parts.push(
9078
- lang === "zh-Hant" ? `\u7528 ${n} \u6B21 AI \u751F\u6210${left == null ? "" : `\uFF08\u4ECA\u5929\u5269 ${left} \u6B21\uFF09`}\u3002` : `Uses ${n} AI generation${n === 1 ? "" : "s"}${left == null ? "" : ` (${left} left today)`}.`
9096
+ lang === "zh-Hant" ? `\u7528 ${n2} \u6B21 AI \u751F\u6210${left == null ? "" : `\uFF08\u4ECA\u5929\u5269 ${left} \u6B21\uFF09`}\u3002` : `Uses ${n2} AI generation${n2 === 1 ? "" : "s"}${left == null ? "" : ` (${left} left today)`}.`
9079
9097
  );
9080
9098
  }
9081
9099
  if (cost.credits) {
9082
- const n = cost.credits;
9100
+ const n2 = cost.credits;
9083
9101
  const left = cost.creditsLeft;
9084
9102
  parts.push(
9085
- lang === "zh-Hant" ? `\u6263 ${n} \u500B\u984D\u5EA6${left == null ? "" : `\uFF08\u5269 ${left}\uFF09`}\u3002` : `Uses ${n} credit${n === 1 ? "" : "s"}${left == null ? "" : ` (${left} left)`}.`
9103
+ lang === "zh-Hant" ? `\u6263 ${n2} \u500B\u984D\u5EA6${left == null ? "" : `\uFF08\u5269 ${left}\uFF09`}\u3002` : `Uses ${n2} credit${n2 === 1 ? "" : "s"}${left == null ? "" : ` (${left} left)`}.`
9086
9104
  );
9087
9105
  }
9088
9106
  return parts.join(" ");
9089
9107
  }
9090
9108
 
9109
+ // ../../packages/mcp/src/messages.ts
9110
+ var UPPER = /* @__PURE__ */ new Set(["seo", "gsc", "gbp", "cta", "cmo", "dns", "ai", "api", "pdf", "url", "id"]);
9111
+ var n = (count, word, plural) => count === 1 ? `1 ${word}` : `${count ? count : "no"} ${plural ?? `${word}s`}`;
9112
+ function titleOf(name) {
9113
+ const words = name.split("_").map((w) => UPPER.has(w) ? w.toUpperCase() : w);
9114
+ const head = words[0] ?? "";
9115
+ return [head.charAt(0).toUpperCase() + head.slice(1), ...words.slice(1)].join(" ");
9116
+ }
9117
+ var LIST_KEYS = ["items", "results", "posts", "ideas", "workspaces", "rows"];
9118
+ function items(value) {
9119
+ if (Array.isArray(value)) return value;
9120
+ if (value && typeof value === "object") {
9121
+ for (const k of LIST_KEYS) {
9122
+ const v = value[k];
9123
+ if (Array.isArray(v)) return v;
9124
+ }
9125
+ }
9126
+ return null;
9127
+ }
9128
+ function label(x) {
9129
+ if (x && typeof x === "object") {
9130
+ const o = x;
9131
+ for (const k of ["title", "name", "domain", "label", "what", "text", "id"]) {
9132
+ if (o[k] !== void 0 && o[k] !== null && o[k] !== "") return String(o[k]);
9133
+ }
9134
+ return Object.entries(o).filter(([, v]) => typeof v !== "object").slice(0, 3).map(([k, v]) => `${k} ${v}`).join(", ");
9135
+ }
9136
+ return String(x);
9137
+ }
9138
+ function bodyLines(value) {
9139
+ const list2 = items(value);
9140
+ if (list2) {
9141
+ const out = list2.slice(0, 8).map((x) => `- ${label(x)}`.slice(0, 200));
9142
+ return list2.length > 8 ? [...out, `\u2026and ${list2.length - 8} more`] : out;
9143
+ }
9144
+ if (value && typeof value === "object") {
9145
+ return Object.entries(value).filter(([k, v]) => v !== null && v !== void 0 && v !== "" && typeof v !== "object" && k !== "next").slice(0, 8).map(([k, v]) => `${k.replace(/_/g, " ")}: ${v}`.slice(0, 200));
9146
+ }
9147
+ return value === null || value === void 0 || value === "" ? [] : [String(value).slice(0, 600)];
9148
+ }
9149
+ function said(name, value) {
9150
+ if (value && typeof value === "object" && !Array.isArray(value)) {
9151
+ for (const k of ["say", "headline", "summary", "message"]) {
9152
+ const v = value[k];
9153
+ if (typeof v === "string" && v.trim()) return (v.trim().split("\n")[0] ?? "").slice(0, 240);
9154
+ }
9155
+ }
9156
+ const list2 = items(value);
9157
+ if (list2) {
9158
+ let noun = name.endsWith("_list") ? name.slice(0, -5).split("_").pop() ?? "item" : "item";
9159
+ if (noun.endsWith("s")) noun = noun.slice(0, -1);
9160
+ return list2.length ? `I found ${n(list2.length, noun)}.` : "There's nothing there yet.";
9161
+ }
9162
+ if (typeof value === "string") return (value.trim().split("\n")[0] ?? "").slice(0, 240) || "Done.";
9163
+ return "Here it is.";
9164
+ }
9165
+ var lowerFirst = (s) => /^[A-Za-z][a-z]/.test(s) ? s.charAt(0).toLowerCase() + s.slice(1) : s;
9166
+ function message(name, value, opts = {}) {
9167
+ const title = titleOf(name);
9168
+ if (opts.error) return { say: `That didn't work: ${opts.error}`.slice(0, 300), title, lines: [] };
9169
+ if (opts.preview) return { say: "This needs your yes first; nothing has changed yet.", title, lines: [opts.preview] };
9170
+ if (opts.done) return { say: `Done: ${lowerFirst(opts.done)}`, title, lines: bodyLines(value) };
9171
+ return { say: said(name, value), title, lines: bodyLines(value) };
9172
+ }
9173
+ function messageText(m) {
9174
+ const body = [m.title ? `**${m.title}**` : "", ...m.lines].filter(Boolean).join("\n");
9175
+ return [m.say, body].filter(Boolean).join("\n\n").trim();
9176
+ }
9177
+
9091
9178
  // ../../packages/tools/src/lib.ts
9092
9179
  var none = { type: "object", properties: {} };
9093
9180
  function ws(ctx) {
9094
9181
  if (!ctx.domain) throw new Error("No website is selected yet. Add one first.");
9095
9182
  return domainApi(ctx.api, ctx.domain);
9096
9183
  }
9097
- var clip = (text3, n = 280) => typeof text3 === "string" ? text3.length > n ? `${text3.slice(0, n)}\u2026` : text3 : text3 ?? null;
9184
+ var clip = (text3, n2 = 280) => typeof text3 === "string" ? text3.length > n2 ? `${text3.slice(0, n2)}\u2026` : text3 : text3 ?? null;
9098
9185
  var plain = (html) => String(html ?? "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
9099
9186
  var untrusted = (value) => ({ untrusted: value });
9100
9187
  function upsert(list2, item2, key) {
9101
9188
  const k = (key(item2) ?? "").trim().toLowerCase();
9102
9189
  const i = list2.findIndex((x) => (key(x) ?? "").trim().toLowerCase() === k);
9103
- return i >= 0 ? list2.map((x, n) => n === i ? { ...x, ...item2 } : x) : [...list2, item2];
9190
+ return i >= 0 ? list2.map((x, n2) => n2 === i ? { ...x, ...item2 } : x) : [...list2, item2];
9104
9191
  }
9105
9192
  function remove(list2, name, key) {
9106
9193
  const k = name.trim().toLowerCase();
@@ -9109,8 +9196,8 @@ function remove(list2, name, key) {
9109
9196
  return out;
9110
9197
  }
9111
9198
  var int = (v, min, max, fallback) => {
9112
- const n = Math.trunc(Number(v));
9113
- return Number.isFinite(n) ? Math.min(max, Math.max(min, n)) : fallback;
9199
+ const n2 = Math.trunc(Number(v));
9200
+ return Number.isFinite(n2) ? Math.min(max, Math.max(min, n2)) : fallback;
9114
9201
  };
9115
9202
  var positionParam = (what, fallback) => ({
9116
9203
  type: "string",
@@ -9279,12 +9366,12 @@ var accountTools = [
9279
9366
  risk: "R0",
9280
9367
  run: async (ctx, { platform }) => {
9281
9368
  const p = platform && CONNECT_FORMS.includes(platform) ? platform : "";
9282
- const label = p ? `Connect ${CONNECT_NAMES[p]}` : "Connect your website";
9369
+ const label2 = p ? `Connect ${CONNECT_NAMES[p]}` : "Connect your website";
9283
9370
  const link = `https://app.cmo.so/posts?connect=${p || "wordpress"}${ctx.domain ? `&site=${encodeURIComponent(ctx.domain)}` : ""}`;
9284
9371
  if (ctx.client === "chat")
9285
9372
  return {
9286
- card: { type: "connect", platform: p || null, label },
9287
- shown: `A "${label}" button now shows under your message. The user fills in the form there; say so in one line.`
9373
+ card: { type: "connect", platform: p || null, label: label2 },
9374
+ shown: `A "${label2}" button now shows under your message. The user fills in the form there; say so in one line.`
9288
9375
  };
9289
9376
  return { link, shown: "Give the user this link: it opens the form in the cmo.so app (web or phone)." };
9290
9377
  }
@@ -9987,10 +10074,10 @@ var brandTools = [
9987
10074
  need: write2,
9988
10075
  risk: "W1",
9989
10076
  run: async (ctx, { count }) => {
9990
- const n = Math.round(Number(count));
9991
- if (!Number.isFinite(n) || n < 0 || n > 10) throw new Error("count must be 0 to 10.");
9992
- const out = await ws(ctx).updateBrand({ internal_links: { count: n } });
9993
- return { internal_links: out.internal_links ?? { count: n } };
10077
+ const n2 = Math.round(Number(count));
10078
+ if (!Number.isFinite(n2) || n2 < 0 || n2 > 10) throw new Error("count must be 0 to 10.");
10079
+ const out = await ws(ctx).updateBrand({ internal_links: { count: n2 } });
10080
+ return { internal_links: out.internal_links ?? { count: n2 } };
9994
10081
  }
9995
10082
  }),
9996
10083
  tool({
@@ -10011,8 +10098,8 @@ var brandTools = [
10011
10098
  risk: "W1",
10012
10099
  run: async (ctx, { use_in_posts, ...item2 }) => {
10013
10100
  const t = (await ws(ctx).brand()).testimonials ?? { enabled: false, items: [] };
10014
- const items = upsert(t.items, item2, (i) => i.name);
10015
- return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items } })).testimonials;
10101
+ const items2 = upsert(t.items, item2, (i) => i.name);
10102
+ return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items: items2 } })).testimonials;
10016
10103
  }
10017
10104
  }),
10018
10105
  tool({
@@ -10030,8 +10117,8 @@ var brandTools = [
10030
10117
  risk: "W1",
10031
10118
  run: async (ctx, { name, use_in_posts }) => {
10032
10119
  const t = (await ws(ctx).brand()).testimonials ?? { enabled: false, items: [] };
10033
- const items = name ? remove(t.items, name, (i) => i.name) : t.items;
10034
- return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items } })).testimonials;
10120
+ const items2 = name ? remove(t.items, name, (i) => i.name) : t.items;
10121
+ return (await ws(ctx).updateBrand({ testimonials: { enabled: use_in_posts ?? t.enabled, items: items2 } })).testimonials;
10035
10122
  }
10036
10123
  }),
10037
10124
  tool({
@@ -10233,7 +10320,7 @@ var brandTools = [
10233
10320
  );
10234
10321
  if (typeof entry === "string") throw new Error(entry);
10235
10322
  if (old && sitemapUrl(old.url) !== entry.url) delete entry.check;
10236
- const next = old ? list2.map((x, n) => n === i ? entry : x) : [...list2, entry];
10323
+ const next = old ? list2.map((x, n2) => n2 === i ? entry : x) : [...list2, entry];
10237
10324
  const problem = checkSitemaps(next);
10238
10325
  if (problem) throw new Error(problem);
10239
10326
  const saved = (await ws(ctx).updateBrand({ sitemaps: next })).sitemaps ?? next;
@@ -10257,7 +10344,7 @@ var brandTools = [
10257
10344
  const list2 = (await ws(ctx).brand()).sitemaps ?? [];
10258
10345
  const i = findSitemap(list2, id, url);
10259
10346
  if (i < 0) throw new Error(`No sitemap ${id ?? url} was found. Use sitemap_list.`);
10260
- const saved = (await ws(ctx).updateBrand({ sitemaps: list2.filter((_, n) => n !== i) })).sitemaps ?? [];
10347
+ const saved = (await ws(ctx).updateBrand({ sitemaps: list2.filter((_, n2) => n2 !== i) })).sitemaps ?? [];
10261
10348
  return { removed: list2[i]?.url, sitemaps: saved.map((s) => s.url) };
10262
10349
  }
10263
10350
  }),
@@ -10416,7 +10503,7 @@ function sitemapResult(s) {
10416
10503
  // ../../packages/tools/src/feedback.ts
10417
10504
  var account = { resource: "account", level: "read" };
10418
10505
  var TYPES = ["bug", "quality", "idea", "praise", "other"];
10419
- var text = (v, n) => String(v ?? "").trim().slice(0, n);
10506
+ var text = (v, n2) => String(v ?? "").trim().slice(0, n2);
10420
10507
  var feedbackTools = [
10421
10508
  tool({
10422
10509
  name: "feedback_send",
@@ -11736,17 +11823,70 @@ var socialTools = [
11736
11823
  const at = positionOf(position);
11737
11824
  const api2 = ws(ctx);
11738
11825
  const results = [];
11739
- for (const n of list2) {
11826
+ for (const n2 of list2) {
11740
11827
  try {
11741
- await api2.approveSocial(n, at);
11742
- results.push({ id: n, ok: true });
11828
+ await api2.approveSocial(n2, at);
11829
+ results.push({ id: n2, ok: true });
11743
11830
  } catch (e) {
11744
- results.push({ id: n, ok: false, error: e instanceof Error ? e.message : String(e) });
11831
+ results.push({ id: n2, ok: false, error: e instanceof Error ? e.message : String(e) });
11745
11832
  }
11746
11833
  }
11747
11834
  return { approved: results.filter((r) => r.ok).length, results };
11748
11835
  }
11749
11836
  }),
11837
+ tool({
11838
+ name: "social_publish_now",
11839
+ description: "Post one social post on its channel now instead of at its posting time: a draft waiting for approval, a queued post, or one that didn't go out. It goes even while posting is paused. It goes out in the background: the answer says it is publishing; read social_post_get after a minute for its link (or why it couldn't go). Not while its picture is being made.",
11840
+ parameters: { type: "object", properties: { id: { type: "integer" } }, required: ["id"] },
11841
+ group: "social",
11842
+ need: write5,
11843
+ risk: "W3",
11844
+ gates: ["VER"],
11845
+ run: async (ctx, { id }) => {
11846
+ const n2 = Number(id);
11847
+ if (!Number.isInteger(n2) || n2 <= 0) throw new Error("Which post?");
11848
+ const post = await ws(ctx).publishSocialNow(n2, { background: true });
11849
+ return post.status === "published" ? post : { ...post, note: "Posting now. Check social_post_get in a minute for its link." };
11850
+ }
11851
+ }),
11852
+ tool({
11853
+ name: "social_posted_update",
11854
+ description: "Change a social post that has already gone out. On LinkedIn the new text replaces the old in place: the post keeps its likes and comments (its pictures can't change this way). With repost, and on Facebook, Instagram and Google, the old post comes down with its likes and comments and the new version goes out now. Without social_copy and with repost, it goes out again as it is (e.g. after new pictures).",
11855
+ parameters: {
11856
+ type: "object",
11857
+ properties: {
11858
+ id: { type: "integer" },
11859
+ social_copy: { type: "string", description: "The post's new text" },
11860
+ repost: { type: "boolean", description: "Take it down and put it up again instead of editing it" }
11861
+ },
11862
+ required: ["id"]
11863
+ },
11864
+ group: "social",
11865
+ need: write5,
11866
+ risk: "W3",
11867
+ gates: ["VER"],
11868
+ run: async (ctx, { id, social_copy, repost }) => {
11869
+ const n2 = Number(id);
11870
+ if (!Number.isInteger(n2) || n2 <= 0) throw new Error("Which post?");
11871
+ const copy = typeof social_copy === "string" ? social_copy.trim() : "";
11872
+ if (!copy && repost !== true) throw new Error("Give the new text (social_copy), or repost: true.");
11873
+ return ws(ctx).republishSocial(n2, copy || void 0, repost === true);
11874
+ }
11875
+ }),
11876
+ tool({
11877
+ name: "social_posted_delete",
11878
+ description: "Take a social post that has gone out down from its channel (LinkedIn, Facebook, Instagram, Google). Its likes and comments go with it; this can't be undone.",
11879
+ parameters: { type: "object", properties: { id: { type: "integer" } }, required: ["id"] },
11880
+ group: "social",
11881
+ need: write5,
11882
+ risk: "W3",
11883
+ gates: ["VER"],
11884
+ run: async (ctx, { id }) => {
11885
+ const n2 = Number(id);
11886
+ if (!Number.isInteger(n2) || n2 <= 0) throw new Error("Which post?");
11887
+ return ws(ctx).deletePostedSocial(n2);
11888
+ }
11889
+ }),
11750
11890
  tool({
11751
11891
  name: "social_skip",
11752
11892
  description: "Skip a LinkedIn post (it won't be posted; it can be restored).",
@@ -13822,8 +13962,8 @@ function prefixIssues(path, issues) {
13822
13962
  return iss;
13823
13963
  });
13824
13964
  }
13825
- function unwrapMessage(message) {
13826
- return typeof message === "string" ? message : message?.message;
13965
+ function unwrapMessage(message2) {
13966
+ return typeof message2 === "string" ? message2 : message2?.message;
13827
13967
  }
13828
13968
  function sizeCaps(defChecks) {
13829
13969
  const caps = [];
@@ -13853,7 +13993,7 @@ function finalizeIssue(iss, ctx, config2) {
13853
13993
  iss.schema = iss.inst;
13854
13994
  }
13855
13995
  const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : void 0;
13856
- const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
13996
+ const message2 = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
13857
13997
  const full = {};
13858
13998
  for (const k of Object.keys(iss)) {
13859
13999
  if (k === "inst" || k === "schema" || k === "continue" || k === "input" || k === "__proto__")
@@ -13861,7 +14001,7 @@ function finalizeIssue(iss, ctx, config2) {
13861
14001
  full[k] = iss[k];
13862
14002
  }
13863
14003
  full.path ?? (full.path = []);
13864
- full.message = message;
14004
+ full.message = message2;
13865
14005
  if (ctx?.reportInput) {
13866
14006
  full.input = iss.input;
13867
14007
  }
@@ -15477,10 +15617,10 @@ function capSize(inst, size) {
15477
15617
  const cap = Math.min(...caps.map((c) => c[0]));
15478
15618
  const parse3 = inst._zod.parse;
15479
15619
  inst._zod.parse = (payload, ctx) => {
15480
- const n = size(payload.value);
15481
- if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
15620
+ const n2 = size(payload.value);
15621
+ if (n2 > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
15482
15622
  for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
15483
- if (n > max && ch._zod.def.when(payload)) {
15623
+ if (n2 > max && ch._zod.def.when(payload)) {
15484
15624
  const start = payload.issues.length;
15485
15625
  ch._zod.check(payload);
15486
15626
  payload.issues[start].continue = false;
@@ -17576,12 +17716,12 @@ function initializeContext(params) {
17576
17716
  external: params?.external ?? void 0
17577
17717
  };
17578
17718
  }
17579
- function handleUnrepresentable(schema, ctx, json, params, message) {
17580
- const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({ zodSchema: schema, path: params.path, message }) : ctx.unrepresentable;
17719
+ function handleUnrepresentable(schema, ctx, json, params, message2) {
17720
+ const result = typeof ctx.unrepresentable === "function" ? ctx.unrepresentable({ zodSchema: schema, path: params.path, message: message2 }) : ctx.unrepresentable;
17581
17721
  if (result === "any")
17582
17722
  return false;
17583
17723
  if (result === void 0 || result === "throw")
17584
- throw new Error(message);
17724
+ throw new Error(message2);
17585
17725
  Object.assign(json, result);
17586
17726
  return true;
17587
17727
  }
@@ -19274,17 +19414,17 @@ var ZodArray = /* @__PURE__ */ $constructor("ZodArray", (inst, def) => {
19274
19414
  inst._zod.processJSONSchema = (ctx, json, params) => arrayProcessor(inst, ctx, json, params);
19275
19415
  inst.element = def.element;
19276
19416
  }, {
19277
- min(n, params) {
19278
- return this.check(_minLength(n, params));
19417
+ min(n2, params) {
19418
+ return this.check(_minLength(n2, params));
19279
19419
  },
19280
19420
  nonempty(params) {
19281
19421
  return this.check(_minLength(1, params));
19282
19422
  },
19283
- max(n, params) {
19284
- return this.check(_maxLength(n, params));
19423
+ max(n2, params) {
19424
+ return this.check(_maxLength(n2, params));
19285
19425
  },
19286
- length(n, params) {
19287
- return this.check(_length(n, params));
19426
+ length(n2, params) {
19427
+ return this.check(_length(n2, params));
19288
19428
  },
19289
19429
  unwrap() {
19290
19430
  return this.element;
@@ -21188,8 +21328,8 @@ var ServerResultSchema = union([
21188
21328
  CreateTaskResultSchema
21189
21329
  ]);
21190
21330
  var McpError = class _McpError extends Error {
21191
- constructor(code, message, data) {
21192
- super(`MCP error ${code}: ${message}`);
21331
+ constructor(code, message2, data) {
21332
+ super(`MCP error ${code}: ${message2}`);
21193
21333
  this.code = code;
21194
21334
  this.data = data;
21195
21335
  this.name = "McpError";
@@ -21197,19 +21337,19 @@ var McpError = class _McpError extends Error {
21197
21337
  /**
21198
21338
  * Factory method to create the appropriate error type based on the error code and data
21199
21339
  */
21200
- static fromError(code, message, data) {
21340
+ static fromError(code, message2, data) {
21201
21341
  if (code === ErrorCode.UrlElicitationRequired && data) {
21202
21342
  const errorData = data;
21203
21343
  if (errorData.elicitations) {
21204
- return new UrlElicitationRequiredError(errorData.elicitations, message);
21344
+ return new UrlElicitationRequiredError(errorData.elicitations, message2);
21205
21345
  }
21206
21346
  }
21207
- return new _McpError(code, message, data);
21347
+ return new _McpError(code, message2, data);
21208
21348
  }
21209
21349
  };
21210
21350
  var UrlElicitationRequiredError = class extends McpError {
21211
- constructor(elicitations, message = `URL elicitation${elicitations.length > 1 ? "s" : ""} required`) {
21212
- super(ErrorCode.UrlElicitationRequired, message, {
21351
+ constructor(elicitations, message2 = `URL elicitation${elicitations.length > 1 ? "s" : ""} required`) {
21352
+ super(ErrorCode.UrlElicitationRequired, message2, {
21213
21353
  elicitations
21214
21354
  });
21215
21355
  }
@@ -21295,15 +21435,15 @@ var Protocol = class {
21295
21435
  let queuedMessage;
21296
21436
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
21297
21437
  if (queuedMessage.type === "response" || queuedMessage.type === "error") {
21298
- const message = queuedMessage.message;
21299
- const requestId = message.id;
21438
+ const message2 = queuedMessage.message;
21439
+ const requestId = message2.id;
21300
21440
  const resolver = this._requestResolvers.get(requestId);
21301
21441
  if (resolver) {
21302
21442
  this._requestResolvers.delete(requestId);
21303
21443
  if (queuedMessage.type === "response") {
21304
- resolver(message);
21444
+ resolver(message2);
21305
21445
  } else {
21306
- const errorMessage3 = message;
21446
+ const errorMessage3 = message2;
21307
21447
  const error2 = new McpError(errorMessage3.error.code, errorMessage3.error.message, errorMessage3.error.data);
21308
21448
  resolver(error2);
21309
21449
  }
@@ -21442,16 +21582,16 @@ var Protocol = class {
21442
21582
  this._onerror(error2);
21443
21583
  };
21444
21584
  const _onmessage = this._transport?.onmessage;
21445
- this._transport.onmessage = (message, extra) => {
21446
- _onmessage?.(message, extra);
21447
- if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {
21448
- this._onresponse(message);
21449
- } else if (isJSONRPCRequest(message)) {
21450
- this._onrequest(message, extra);
21451
- } else if (isJSONRPCNotification(message)) {
21452
- this._onnotification(message);
21585
+ this._transport.onmessage = (message2, extra) => {
21586
+ _onmessage?.(message2, extra);
21587
+ if (isJSONRPCResultResponse(message2) || isJSONRPCErrorResponse(message2)) {
21588
+ this._onresponse(message2);
21589
+ } else if (isJSONRPCRequest(message2)) {
21590
+ this._onrequest(message2, extra);
21591
+ } else if (isJSONRPCNotification(message2)) {
21592
+ this._onnotification(message2);
21453
21593
  } else {
21454
- this._onerror(new Error(`Unknown message type: ${JSON.stringify(message)}`));
21594
+ this._onerror(new Error(`Unknown message type: ${JSON.stringify(message2)}`));
21455
21595
  }
21456
21596
  };
21457
21597
  await this._transport.start();
@@ -22061,12 +22201,12 @@ var Protocol = class {
22061
22201
  * the error appropriately (e.g., by failing the task, logging, etc.). The Protocol layer
22062
22202
  * simply propagates the error.
22063
22203
  */
22064
- async _enqueueTaskMessage(taskId, message, sessionId) {
22204
+ async _enqueueTaskMessage(taskId, message2, sessionId) {
22065
22205
  if (!this._taskStore || !this._taskMessageQueue) {
22066
22206
  throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
22067
22207
  }
22068
22208
  const maxQueueSize = this._options?.maxTaskQueueSize;
22069
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
22209
+ await this._taskMessageQueue.enqueue(taskId, message2, sessionId, maxQueueSize);
22070
22210
  }
22071
22211
  /**
22072
22212
  * Clears the message queue for a task and rejects any pending request resolvers.
@@ -22076,9 +22216,9 @@ var Protocol = class {
22076
22216
  async _clearTaskQueue(taskId, sessionId) {
22077
22217
  if (this._taskMessageQueue) {
22078
22218
  const messages = await this._taskMessageQueue.dequeueAll(taskId, sessionId);
22079
- for (const message of messages) {
22080
- if (message.type === "request" && isJSONRPCRequest(message.message)) {
22081
- const requestId = message.message.id;
22219
+ for (const message2 of messages) {
22220
+ if (message2.type === "request" && isJSONRPCRequest(message2.message)) {
22221
+ const requestId = message2.message.id;
22082
22222
  const resolver = this._requestResolvers.get(requestId);
22083
22223
  if (resolver) {
22084
22224
  resolver(new McpError(ErrorCode.InternalError, "Task cancelled or completed"));
@@ -23243,14 +23383,14 @@ function toolArgs(args) {
23243
23383
  return out;
23244
23384
  }
23245
23385
  function withIdempotency(api2, approvalId) {
23246
- let n = 0;
23386
+ let n2 = 0;
23247
23387
  return {
23248
23388
  ...api2,
23249
23389
  request: (path, init = {}) => {
23250
23390
  const method = (init.method ?? "GET").toUpperCase();
23251
23391
  if (method === "GET" || method === "HEAD") return api2.request(path, init);
23252
23392
  const headers = new Headers(init.headers);
23253
- headers.set("Idempotency-Key", idempotencyKey(approvalId, 0, n++));
23393
+ headers.set("Idempotency-Key", idempotencyKey(approvalId, 0, n2++));
23254
23394
  return api2.request(path, { ...init, headers });
23255
23395
  }
23256
23396
  };
@@ -23258,13 +23398,18 @@ function withIdempotency(api2, approvalId) {
23258
23398
  var text2 = (value) => [
23259
23399
  { type: "text", text: typeof value === "string" ? value : JSON.stringify(value) }
23260
23400
  ];
23261
- function ok(result, extra) {
23401
+ function ok(result, extra, msg) {
23262
23402
  const value = result ?? { ok: true };
23263
23403
  const structured = value && typeof value === "object" && !Array.isArray(value) ? value : { items: value };
23264
- return { content: text2(value), structuredContent: { ...structured, ...extra } };
23404
+ if (!msg) return { content: text2(value), structuredContent: { ...structured, ...extra } };
23405
+ return {
23406
+ content: [...text2(messageText(msg)), ...text2(value)],
23407
+ structuredContent: { ...structured, ...extra, message: msg }
23408
+ };
23265
23409
  }
23266
- function fail(message) {
23267
- return { content: text2({ error: message }), isError: true };
23410
+ function fail(error2, tool2) {
23411
+ if (!tool2) return { content: text2({ error: error2 }), isError: true };
23412
+ return { content: [...text2(messageText(message(tool2, void 0, { error: error2 }))), ...text2({ error: error2 })], isError: true };
23268
23413
  }
23269
23414
  function errorMessage2(e) {
23270
23415
  if (e instanceof SignInRequiredError) return "The sign-in has expired. Reconnect CMO.so and try again.";
@@ -23404,7 +23549,10 @@ function createMcpServer(deps) {
23404
23549
  );
23405
23550
  const callArgs = approval ? withFreshFiles(t, approval.calls[0]?.args ?? {}, toolArgs(args)) : toolArgs(args);
23406
23551
  const ctx = { api: api2, domain, client: "mcp" };
23407
- if (!isWrite(t)) return ok(await t.run(ctx, callArgs), viewForTool(t.name) ? { workspace: domain } : void 0);
23552
+ if (!isWrite(t)) {
23553
+ const value = await t.run(ctx, callArgs);
23554
+ return ok(value, viewForTool(t.name) ? { workspace: domain } : void 0, message(t.name, value));
23555
+ }
23408
23556
  let standing = null;
23409
23557
  if (!approval && !deps.previewOnly && domain && isStanding(t.name)) {
23410
23558
  const claim2 = await api2.account?.claimStanding({ website: domain, tool: t.name, units: standingUnits(t.name, callArgs) }).catch(() => null);
@@ -23426,14 +23574,19 @@ function createMcpServer(deps) {
23426
23574
  const calls = [{ name: t.name, args: callArgs }];
23427
23575
  const summary2 = t.confirm?.(callArgs, "en") ?? t.description;
23428
23576
  const cost = await previewCost(api2, domain, t);
23429
- return ok({
23430
- status: "needs_confirmation",
23431
- preview: cost ? `${summary2} ${cost}` : summary2,
23432
- risk: t.risk,
23433
- workspace: domain,
23434
- confirmation: signer.sign({ calls, principal, domain }),
23435
- next: "Show the preview to the user. If they agree, call this tool again with confirm: true and this confirmation (it runs exactly what was previewed). Nothing has changed yet."
23436
- });
23577
+ const preview = cost ? `${summary2} ${cost}` : summary2;
23578
+ return ok(
23579
+ {
23580
+ status: "needs_confirmation",
23581
+ preview,
23582
+ risk: t.risk,
23583
+ workspace: domain,
23584
+ confirmation: signer.sign({ calls, principal, domain }),
23585
+ next: "Show the preview to the user. If they agree, call this tool again with confirm: true and this confirmation (it runs exactly what was previewed). Nothing has changed yet."
23586
+ },
23587
+ void 0,
23588
+ message(t.name, void 0, { preview })
23589
+ );
23437
23590
  }
23438
23591
  const summary = `${t.confirm?.(callArgs, "en") ?? t.description}${standing ? ` (standing permission #${standing})` : ""}`;
23439
23592
  try {
@@ -23441,14 +23594,14 @@ function createMcpServer(deps) {
23441
23594
  const added = t.name === "website_add" ? result?.domain : null;
23442
23595
  const where = typeof added === "string" && added ? added : domain;
23443
23596
  await deps.audit?.({ domain: where, actions: [{ tool: t.name, summary, ok: true, action_id: approval.id }] }).catch(() => void 0);
23444
- return ok(result);
23597
+ return ok(result, void 0, message(t.name, result, { done: summary }));
23445
23598
  } catch (e) {
23446
23599
  const error2 = errorMessage2(e);
23447
23600
  await deps.audit?.({ domain, actions: [{ tool: t.name, summary, ok: false, error: error2, action_id: approval.id }] }).catch(() => void 0);
23448
- return fail(error2);
23601
+ return fail(error2, t.name);
23449
23602
  }
23450
23603
  } catch (e) {
23451
- return fail(errorMessage2(e));
23604
+ return fail(errorMessage2(e), t.name);
23452
23605
  }
23453
23606
  });
23454
23607
  server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => ({
@@ -23578,8 +23731,8 @@ var ReadBuffer = class {
23578
23731
  function deserializeMessage(line) {
23579
23732
  return JSONRPCMessageSchema.parse(JSON.parse(line));
23580
23733
  }
23581
- function serializeMessage(message) {
23582
- return JSON.stringify(message) + "\n";
23734
+ function serializeMessage(message2) {
23735
+ return JSON.stringify(message2) + "\n";
23583
23736
  }
23584
23737
 
23585
23738
  // ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.30.1_zod@4.6.7/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
@@ -23617,11 +23770,11 @@ var StdioServerTransport = class {
23617
23770
  processReadBuffer() {
23618
23771
  while (true) {
23619
23772
  try {
23620
- const message = this._readBuffer.readMessage();
23621
- if (message === null) {
23773
+ const message2 = this._readBuffer.readMessage();
23774
+ if (message2 === null) {
23622
23775
  break;
23623
23776
  }
23624
- this.onmessage?.(message);
23777
+ this.onmessage?.(message2);
23625
23778
  } catch (error2) {
23626
23779
  this.onerror?.(error2);
23627
23780
  }
@@ -23637,9 +23790,9 @@ var StdioServerTransport = class {
23637
23790
  this._readBuffer.clear();
23638
23791
  this.onclose?.();
23639
23792
  }
23640
- send(message) {
23793
+ send(message2) {
23641
23794
  return new Promise((resolve) => {
23642
- const json = serializeMessage(message);
23795
+ const json = serializeMessage(message2);
23643
23796
  if (this._stdout.write(json)) {
23644
23797
  resolve();
23645
23798
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmo-so/mcp",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "CMO.so's MCP server for Claude Desktop, Cursor, VS Code and other MCP clients: manage your websites, blog posts, LinkedIn queue and results with Maggie.",
5
5
  "type": "module",
6
6
  "license": "MIT",