@cmo-so/cli 0.9.1 → 0.9.2

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.mjs +85 -3
  2. package/package.json +1 -1
package/dist/cmo.mjs CHANGED
@@ -7724,8 +7724,14 @@ function domainApi(api2, domain) {
7724
7724
  /** How a posted Instagram post is doing (read from Instagram, kept 15 minutes; `refresh` reads again). */
7725
7725
  socialInsights: (id, refresh = false) => api2.request(`${base}/social/${id}/insights${refresh ? "?refresh=true" : ""}`),
7726
7726
  deletePostedSocial: (id) => api2.request(`${base}/social/${id}/published`, { method: "DELETE" }),
7727
- /** Change a posted LinkedIn post and put it up again: the old one comes down, the new text goes out now. */
7728
- republishSocial: (id, socialCopy) => post(`${base}/social/${id}/republish`, socialCopy ? { social_copy: socialCopy } : {}),
7727
+ /**
7728
+ * Change a posted post. LinkedIn changes its text in place (likes and comments stay); with `repost`, and on
7729
+ * the other channels, the old one comes down and the new text goes out now.
7730
+ */
7731
+ republishSocial: (id, socialCopy, repost = false) => post(`${base}/social/${id}/republish`, {
7732
+ ...socialCopy ? { social_copy: socialCopy } : {},
7733
+ ...repost ? { repost: true } : {}
7734
+ }),
7729
7735
  restoreSocial: (id) => post(`${base}/social/${id}/restore`),
7730
7736
  pauseSocial: () => post(`${base}/social/pause`),
7731
7737
  /**
@@ -8725,6 +8731,18 @@ var confirmCopy = {
8725
8731
  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`;
8726
8732
  }
8727
8733
  },
8734
+ social_publish_now: {
8735
+ 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.`,
8736
+ "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`
8737
+ },
8738
+ social_posted_update: {
8739
+ 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.`,
8740
+ "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`
8741
+ },
8742
+ social_posted_delete: {
8743
+ en: (a) => `Take post #${a.id} down from its channel, with its likes and comments. This can't be undone.`,
8744
+ "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`
8745
+ },
8728
8746
  social_skip: { en: (a) => `Skip post #${a.id}.`, "zh-Hant": (a) => `\u8DF3\u904E\u8CBC\u6587 #${a.id}\u3002` },
8729
8747
  social_restore: {
8730
8748
  en: (a) => `Bring back post #${a.id}.`,
@@ -11687,6 +11705,59 @@ var socialTools = [
11687
11705
  return { approved: results.filter((r) => r.ok).length, results };
11688
11706
  }
11689
11707
  }),
11708
+ tool({
11709
+ name: "social_publish_now",
11710
+ 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.",
11711
+ parameters: { type: "object", properties: { id: { type: "integer" } }, required: ["id"] },
11712
+ group: "social",
11713
+ need: write5,
11714
+ risk: "W3",
11715
+ gates: ["VER"],
11716
+ run: async (ctx, { id }) => {
11717
+ const n = Number(id);
11718
+ if (!Number.isInteger(n) || n <= 0) throw new Error("Which post?");
11719
+ const post = await ws(ctx).publishSocialNow(n, { background: true });
11720
+ return post.status === "published" ? post : { ...post, note: "Posting now. Check social_post_get in a minute for its link." };
11721
+ }
11722
+ }),
11723
+ tool({
11724
+ name: "social_posted_update",
11725
+ 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).",
11726
+ parameters: {
11727
+ type: "object",
11728
+ properties: {
11729
+ id: { type: "integer" },
11730
+ social_copy: { type: "string", description: "The post's new text" },
11731
+ repost: { type: "boolean", description: "Take it down and put it up again instead of editing it" }
11732
+ },
11733
+ required: ["id"]
11734
+ },
11735
+ group: "social",
11736
+ need: write5,
11737
+ risk: "W3",
11738
+ gates: ["VER"],
11739
+ run: async (ctx, { id, social_copy, repost }) => {
11740
+ const n = Number(id);
11741
+ if (!Number.isInteger(n) || n <= 0) throw new Error("Which post?");
11742
+ const copy = typeof social_copy === "string" ? social_copy.trim() : "";
11743
+ if (!copy && repost !== true) throw new Error("Give the new text (social_copy), or repost: true.");
11744
+ return ws(ctx).republishSocial(n, copy || void 0, repost === true);
11745
+ }
11746
+ }),
11747
+ tool({
11748
+ name: "social_posted_delete",
11749
+ 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.",
11750
+ parameters: { type: "object", properties: { id: { type: "integer" } }, required: ["id"] },
11751
+ group: "social",
11752
+ need: write5,
11753
+ risk: "W3",
11754
+ gates: ["VER"],
11755
+ run: async (ctx, { id }) => {
11756
+ const n = Number(id);
11757
+ if (!Number.isInteger(n) || n <= 0) throw new Error("Which post?");
11758
+ return ws(ctx).deletePostedSocial(n);
11759
+ }
11760
+ }),
11690
11761
  tool({
11691
11762
  name: "social_skip",
11692
11763
  description: "Skip a LinkedIn post (it won't be posted; it can be restored).",
@@ -16545,7 +16616,7 @@ var program = new Command();
16545
16616
  // package.json
16546
16617
  var package_default = {
16547
16618
  name: "@cmo-so/cli",
16548
- version: "0.9.1",
16619
+ version: "0.9.2",
16549
16620
  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.",
16550
16621
  type: "module",
16551
16622
  license: "MIT",
@@ -27571,6 +27642,17 @@ social.command("carousel <id>").description("a LinkedIn post with a set of pictu
27571
27642
  });
27572
27643
  })
27573
27644
  );
27645
+ social.command("post-now <id>").description("post it on its channel now, not at its posting time (even while posting is paused)").action(act(async (opts, id) => tool2(opts, "social_publish_now", { id: ids2([id])[0] })));
27646
+ social.command("edit-posted <id> [text...]").description("change a post that has gone out (LinkedIn edits it in place, keeping likes and comments)").option("--repost", "take it down and put it up again instead").action(
27647
+ act(
27648
+ async (opts, id, text3) => tool2(opts, "social_posted_update", {
27649
+ id: ids2([id])[0],
27650
+ ...text3.length ? { social_copy: text3.join(" ") } : {},
27651
+ ...opts.repost ? { repost: true } : {}
27652
+ })
27653
+ )
27654
+ );
27655
+ social.command("delete-posted <id>").description("take a post that has gone out down from its channel, with its likes and comments").action(act(async (opts, id) => tool2(opts, "social_posted_delete", { id: ids2([id])[0] })));
27574
27656
  social.command("skip <id>").description("skip a draft").action(act(async (opts, id) => tool2(opts, "social_skip", { id: ids2([id])[0] })));
27575
27657
  social.command("restore <id>").description("bring a skipped draft back").action(act(async (opts, id) => tool2(opts, "social_restore", { id: ids2([id])[0] })));
27576
27658
  social.command("draft <topic...>").description("add a post idea for Maggie to write (every connected channel unless --channel)").option("--summary <text>", "what the post should say").option("--channel <names>", "linkedin, facebook, instagram, google_business (comma-separated)").action(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmo-so/cli",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "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.",
5
5
  "type": "module",
6
6
  "license": "MIT",