hermoso 0.1.541 → 0.1.542
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/http.mjs +1 -1
- package/mcp/tools.mjs +5 -0
- package/package.json +1 -1
package/mcp/http.mjs
CHANGED
|
@@ -599,7 +599,7 @@ const inflightNameOf = (body) => { const msgs = Array.isArray(body) ? body : [bo
|
|
|
599
599
|
const baseInstructions = instructionsFor(scope, { widgetHost });
|
|
600
600
|
let firstRun = null;
|
|
601
601
|
if (typeof firstRunFor === 'function' && user.accountId) {
|
|
602
|
-
try { firstRun = await Promise.race([Promise.resolve(firstRunFor({ accountId: user.accountId })).catch(() => null), new Promise((r) => { const t = setTimeout(() => r(null), 1500); if (t && typeof t.unref === 'function') t.unref(); })]); } catch { firstRun = null; }
|
|
602
|
+
try { firstRun = await Promise.race([Promise.resolve(firstRunFor({ accountId: user.accountId, brandKey: user.brandKey === true })).catch(() => null), new Promise((r) => { const t = setTimeout(() => r(null), 1500); if (t && typeof t.unref === 'function') t.unref(); })]); } catch { firstRun = null; }
|
|
603
603
|
}
|
|
604
604
|
firstRun = firstRun && typeof firstRun === 'object' && firstRun.fresh === true ? { ...firstRun, offer: firstRunOffers(baseInstructions) } : null;
|
|
605
605
|
const server = new McpServer({ name: 'hermoso', version: PKG_VERSION }, { instructions: withFirstRunLine(baseInstructions, firstRun) });
|
package/mcp/tools.mjs
CHANGED
|
@@ -6650,6 +6650,9 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
6650
6650
|
// ZERO BRANDS IS A REAL STATE (2026-10-01): the owner may delete their last brand. Say so, and say how to make one,
|
|
6651
6651
|
// rather than printing an empty list under a heading that implies there should be something in it.
|
|
6652
6652
|
if (!(d.brands || []).length) return ok(`This account has no profiles yet (the last one was deleted, or none was ever made). create_brand makes one, and draft_brand fills it in from a website, a description or a social handle.${sharedTxt}`, { ...d, sharedWorkspaces: shared });
|
|
6653
|
+
// A KEY LIMITED TO ONE BRAND lists that brand and says so (the server filters the roster and sends the sentence),
|
|
6654
|
+
// so an agent does not go looking for profiles it was never given.
|
|
6655
|
+
if (d.limited && d.limited.sentence) return ok(`${d.limited.sentence} It is the only profile this connection can see or act on:\n${lines}${sharedTxt}`, { ...d, sharedWorkspaces: shared });
|
|
6653
6656
|
return ok(`Profiles on this account:\n${lines}\n\nSwitch with use_brand.${sharedTxt}`, { ...d, sharedWorkspaces: shared });
|
|
6654
6657
|
}));
|
|
6655
6658
|
|
|
@@ -6699,6 +6702,8 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
6699
6702
|
return ok(`Now acting on ${sh.name || 'that shared profile'}${sh.ownerName ? ` (${sh.ownerName}'s profile)` : ''} (profile ${sh.profileUuid}). Its brand details, memory, Library and CONNECTED ACCOUNTS are what every tool sees from here; switch back by naming one of your own profiles.`,
|
|
6700
6703
|
{ ok: true, brand: { id: sh.profileUuid, name: sh.name || null, ownerAccountId: sh.ownerAccountId, role: sh.role || 'member' }, shared: true });
|
|
6701
6704
|
}
|
|
6705
|
+
// A key limited to one brand cannot switch, and says so in the server's own sentence instead of "no such profile".
|
|
6706
|
+
if (d.limited && d.limited.sentence) return { content: [{ type: 'text', text: `${d.limited.sentence} It cannot switch to another brand.` }], isError: true };
|
|
6702
6707
|
const own = (d.brands || []).map(b => `• ${b.name} (id: ${b.id})`).join('\n');
|
|
6703
6708
|
const shr = shared.map(w => `• ${w.name || 'Shared profile'}${w.ownerName ? ` — ${w.ownerName}` : ''} (id: ${w.profileUuid}, shared with you)`).join('\n');
|
|
6704
6709
|
if (!own && !shr) return { content: [{ type: 'text', text: `No profile matching "${brand}": this account has no profiles yet. create_brand makes one.` }], isError: true }; // zero brands is a real state (2026-10-01)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermoso",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.542",
|
|
4
4
|
"mcpName": "io.github.hermoso-ai/hermoso",
|
|
5
5
|
"description": "AI marketing agent and AI ad generator, run from your own AI agent. 1233 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 5 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",
|