hermoso 0.1.514 → 0.1.515
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.
- package/mcp/tools.mjs +8 -1
- package/package.json +1 -1
package/mcp/tools.mjs
CHANGED
|
@@ -474,6 +474,11 @@ async function imageBlock(url) {
|
|
|
474
474
|
// "connect your … account" — those are precisely the two alternatives that swallowed the refusals above. The branch
|
|
475
475
|
// retires the day that throw becomes notConnected('microsoft_onedrive'); nothing else has to move.
|
|
476
476
|
const NOT_CONNECTED_LEGACY_RE = /isn['’`]?t connected\b|\bConnect [A-Z][\w .+&-]{1,28} first\b/;
|
|
477
|
+
// A WRONG ID IS NOT A MISSING CONNECTION (2026-11-04, live on schedule_post): "Page 999… isn’t connected to this brand.
|
|
478
|
+
// Connected Page: …" is a refusal on a connector that WORKS, about an id that is not one of this brand's, and it already
|
|
479
|
+
// names the right ones. "Ask your human to connect it" sent the agent to reconnect Meta. An id as the subject, or a list
|
|
480
|
+
// of what IS connected, marks that class; the legacy branch above is only for a connection that is absent outright.
|
|
481
|
+
const WRONG_ID_RE = /\d{4,}\)?\s+isn['’`]?t connected to this\b|\bConnected [A-Z]?[a-z]+(?: [a-z]+)?s?:\s/;
|
|
477
482
|
// LEGACY-ONLY provider resolution, reached solely by the branch above. It is order-sensitive in a way that bites
|
|
478
483
|
// (/tiktok/ matches "TikTok Ads", so the ads entries MUST precede the organic ones) and it has always been missing
|
|
479
484
|
// live providers — which is exactly the fragility the marker removes, and exactly why nothing on the marker path
|
|
@@ -507,6 +512,8 @@ function notConnectedHint(e, msg) {
|
|
|
507
512
|
if (status === 401) return marker ? ((/\?connect=[a-z_]/.test(String(msg || '')) ? '' : CONNECT_LINK_HINT(marker, e?.connectUrl)) + KEY_CONNECT_HINT(marker, msg)) : '';
|
|
508
513
|
if (marker) return ''; // connected already — a sharing / ownership / provider refusal that merely names its connector
|
|
509
514
|
if (status === 501) return ''; // a provider key WE have not set; no user connection can supply it
|
|
515
|
+
if (e?.apiCode) return ''; // the server classified it with its own code, so it is not the unclassified legacy throw (a wrong Page id is `meta_page_not_connected`)
|
|
516
|
+
if (WRONG_ID_RE.test(String(msg || ''))) return ''; // a wrong id on a working connector, from a server that sent no code
|
|
510
517
|
if (!NOT_CONNECTED_LEGACY_RE.test(String(msg || ''))) return '';
|
|
511
518
|
const hit = CONNECT_LEGACY_PROVIDERS.find(([re]) => re.test(msg));
|
|
512
519
|
return hit ? CONNECT_LINK_HINT(hit[1]) : CONNECT_ASK_HINT;
|
|
@@ -6743,7 +6750,7 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
6743
6750
|
// no need for one edge case just for Facebook."
|
|
6744
6751
|
server.registerTool('schedule_post', {
|
|
6745
6752
|
title: 'Schedule a post for later',
|
|
6746
|
-
description: 'Use this when the user wants to schedule a social media post for later, on one channel or several at once. Scheduling and publishing cost no credits on any Hermoso plan (X alone bills per call: hermoso_credits gives the exact credits per X post). THE FREE PLAN INCLUDES 10 POSTS A MONTH ON UP TO 3 CHANNELS (a post counts once, however many channels it goes to; counted in the UTC month the post goes out); every paid plan posts without a limit. A post over that allowance is refused here and nothing is queued; the refusal says how many are used and when the count resets. Relay it as written, never retry it and never split the post to fit. billing_status and list_scheduled show how many are used. Queue a post for a future time on one or more connected channels at once: facebook, instagram, threads, tiktok, youtube, linkedin, x, pinterest, bluesky, telegram, wordpress, discord, slack — every one live. whop works where its connector is offered (list_connectors says) and is held back elsewhere: there a whop post is refused, not queued. A MULTI-SLIDE creative goes in imageUrls[] as a CAROUSEL, in order — never schedule just its first slide. Name the time in `at`, or pass `useQueue:true` for the brand’s next free POSTING SLOT (what “just queue it” means). imageUrl/videoUrl take a Hermoso render URL or an upload_file URL. `captions` gives a channel its own wording; the rest use `message`. PINTEREST AND YOUTUBE SHOW A TITLE: `title` (max 100 chars), derived from the caption when omitted; YOUTUBE also takes `description`, `tags`, `thumbnailUrl`. Every PER-CHANNEL SETTING is a parameter below, carried straight to the real publisher — TikTok’s `brandedContent` / `yourBrand` disclosures (set them whenever the post is commercial), Google Business `topicType` / `event` / `offer` / `actionType`, an X `thread` / `poll`, Instagram `collaborators`, and the rest. Channels are attempted INDEPENDENTLY: one failing never blocks the others. SOME CHANNELS MUST BE TOLD WHICH ACCOUNT, and Hermoso never guesses: Pinterest needs `boardId` (list_pinterest_boards) or is refused; a LinkedIn COMPANY PAGE post needs `linkedinOrganizationId` (list_linkedin_pages) or it goes to the person’s own profile
|
|
6753
|
+
description: 'Use this when the user wants to schedule a social media post for later, on one channel or several at once. Scheduling and publishing cost no credits on any Hermoso plan (X alone bills per call: hermoso_credits gives the exact credits per X post). THE FREE PLAN INCLUDES 10 POSTS A MONTH ON UP TO 3 CHANNELS (a post counts once, however many channels it goes to; counted in the UTC month the post goes out); every paid plan posts without a limit. A post over that allowance is refused here and nothing is queued; the refusal says how many are used and when the count resets. Relay it as written, never retry it and never split the post to fit. billing_status and list_scheduled show how many are used. Queue a post for a future time on one or more connected channels at once: facebook, instagram, threads, tiktok, youtube, linkedin, x, pinterest, bluesky, telegram, wordpress, discord, slack — every one live. whop works where its connector is offered (list_connectors says) and is held back elsewhere: there a whop post is refused, not queued. A MULTI-SLIDE creative goes in imageUrls[] as a CAROUSEL, in order — never schedule just its first slide. Name the time in `at`, or pass `useQueue:true` for the brand’s next free POSTING SLOT (what “just queue it” means). imageUrl/videoUrl take a Hermoso render URL or an upload_file URL. `captions` gives a channel its own wording; the rest use `message`. PINTEREST AND YOUTUBE SHOW A TITLE: `title` (max 100 chars), derived from the caption when omitted; YOUTUBE also takes `description`, `tags`, `thumbnailUrl`. Every PER-CHANNEL SETTING is a parameter below, carried straight to the real publisher — TikTok’s `brandedContent` / `yourBrand` disclosures (set them whenever the post is commercial), Google Business `topicType` / `event` / `offer` / `actionType`, an X `thread` / `poll`, Instagram `collaborators`, and the rest. Channels are attempted INDEPENDENTLY: one failing never blocks the others. SOME CHANNELS MUST BE TOLD WHICH ACCOUNT, and Hermoso never guesses: Pinterest needs `boardId` (list_pinterest_boards) or is refused; a LinkedIn COMPANY PAGE post needs `linkedinOrganizationId` (list_linkedin_pages) or it goes to the person’s own profile. Several Facebook Pages need `pageId` (list_meta_pages): a Facebook post on a brand with several Pages and none named is refused when you schedule it, with the Pages listed by name and id, so ask the user which one. Several Google Business listings need `locationId` (list_business_locations), and without it that post is refused when it fires. Resolve those FIRST and let the user pick. A scheduled post GOES LIVE PUBLICLY by default on every channel, never quietly downgraded. Only if the user asks, set `visibility` (or `visibilityByChannel`): ‘unlisted’ (YouTube) · ‘private’ (YouTube, or TikTok SELF_ONLY) · ‘draft’ (TikTok, or an unpublished Facebook Page post). A visibility a channel cannot do is REFUSED now, never posted weaker later.',
|
|
6747
6754
|
inputSchema: {
|
|
6748
6755
|
...HOOK_ATTR,
|
|
6749
6756
|
channels: z.array(z.enum(['facebook', 'instagram', 'threads', 'tiktok', 'youtube', 'linkedin', 'x', 'pinterest', 'google_business', 'bluesky', 'telegram', 'wordpress', 'discord', 'slack', 'whop'])).describe('one or more channels to post to at that time'),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermoso",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.515",
|
|
4
4
|
"mcpName": "io.github.hermoso-ai/hermoso",
|
|
5
5
|
"description": "AI marketing agent and AI ad generator, run from your own AI agent. 1175 tools. No markup on models on Starter and up. Publishing, scheduling, ad campaign management, comments, DMs and analytics cost no credits on any plan; Free includes 10 posts a month and every paid plan posts without a limit. AD PLATFORMS: Meta, Google Ads, TikTok Ads, LinkedIn Ads, Reddit Ads, X Ads, Pinterest Ads, Snapchat Ads, Microsoft Advertising, Apple Search Ads, ChatGPT Ads and AppLovin Ads, plus product feeds in Google Merchant Center. PUBLISHING AND SCHEDULING: Facebook, Instagram, Threads, TikTok, YouTube, X, LinkedIn, Pinterest, Bluesky, Telegram, WordPress, Discord, Slack, Whop and Google Business Profile. INSTAGRAM DM AUTOMATIONS: a keyword comment, a DM, a story reply or an ig.me link gets an automatic private reply from the brand. AD RESEARCH: the Meta, Google and LinkedIn ad libraries plus organic TikTok, Instagram, YouTube, Threads and Reddit. ANALYTICS: Google Analytics 4, Google Search Console and every connected platform's own post and campaign insights. Also brand onboarding, 50+ image and video generation models, ad scoring, competitor teardowns, Google Drive and OneDrive, a CLI and installable Claude skills.",
|
|
6
6
|
"type": "module",
|