hermoso 0.1.207 → 0.1.209
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 +6 -2
- package/package.json +1 -1
package/mcp/tools.mjs
CHANGED
|
@@ -16109,7 +16109,7 @@ function memoryNoteVerdict(text) {
|
|
|
16109
16109
|
},
|
|
16110
16110
|
outputSchema: {
|
|
16111
16111
|
collections: z.array(z.any()).optional().describe('the named collections ({id, name, ads} counts)'),
|
|
16112
|
-
ads: z.array(z.any()).optional().describe('the saved ads ({key, collection, advertiser, title, body, image, video, link, platform, savedAt, tags}); a saved CREATOR (platform "creator") also carries `creator` — handle, platform, email, phone, link, category, followers, posts, medianPlays, engagementRate, score, profileUrl'),
|
|
16112
|
+
ads: z.array(z.any()).optional().describe('the saved ads ({key, collection, advertiser, title, body, image, video, link, platform, savedAt, tags}); a saved CREATOR (platform "creator") also carries `creator` — handle, platform, email, phone, link, category, followers, posts, medianPlays, engagementRate, score, profileUrl, outreach {status new|contacted|replied|booked|passed, note} (set with update_saved_creator)'),
|
|
16113
16113
|
total: z.number().optional().describe('how many ads the board holds in total, before any collection filter or limit'),
|
|
16114
16114
|
},
|
|
16115
16115
|
annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
|
|
@@ -16121,7 +16121,7 @@ function memoryNoteVerdict(text) {
|
|
|
16121
16121
|
if (want && !hit) return { content: [{ type: 'text', text: `No swipefile collection called "${a.collection}". This board has: ${s.collections.map(c => c.name).join(', ') || '(none)'}.` }], isError: true };
|
|
16122
16122
|
const nameOf = (id) => (s.collections.find(c => c.id === id) || {}).name || 'My Swipefile';
|
|
16123
16123
|
const rows = s.ads.filter(x => x && (!hit || x.collectionId === hit.id));
|
|
16124
|
-
const ads = rows.slice(0, lim).map(x => ({ key: x.key, collection: nameOf(x.collectionId), advertiser: x.advertiser || '', title: x.title || '', body: String(x.body || '').slice(0, 400), image: abs(x.image || ''), video: abs(x.video || ''), link: x.link || '', platform: x.platform || '', savedAt: x.savedAt || 0, tags: x.tags || null, ...(x.platform === 'creator' && x.creator ? { creator: { handle: x.creator.handle, platform: x.creator.platform, name: x.creator.name, email: x.creator.email || null, phone: x.creator.phone || null, link: x.creator.link || null, category: x.creator.category || null, followers: x.creator.followers ?? null, posts: x.creator.posts, medianPlays: x.creator.medianPlays, engagementRate: x.creator.engagementRate ?? null, score: x.creator.score, profileUrl: x.creator.profileUrl || '' } } : {}) }));
|
|
16124
|
+
const ads = rows.slice(0, lim).map(x => ({ key: x.key, collection: nameOf(x.collectionId), advertiser: x.advertiser || '', title: x.title || '', body: String(x.body || '').slice(0, 400), image: abs(x.image || ''), video: abs(x.video || ''), link: x.link || '', platform: x.platform || '', savedAt: x.savedAt || 0, tags: x.tags || null, ...(x.platform === 'creator' && x.creator ? { creator: { handle: x.creator.handle, platform: x.creator.platform, name: x.creator.name, email: x.creator.email || null, phone: x.creator.phone || null, link: x.creator.link || null, category: x.creator.category || null, followers: x.creator.followers ?? null, posts: x.creator.posts, medianPlays: x.creator.medianPlays, engagementRate: x.creator.engagementRate ?? null, score: x.creator.score, profileUrl: x.creator.profileUrl || '', outreach: x.creator.outreach || { status: 'new', note: '' } } } : {}) }));
|
|
16125
16125
|
const collections = s.collections.map(c => ({ id: c.id, name: c.name, ads: s.ads.filter(x => x && x.collectionId === c.id).length }));
|
|
16126
16126
|
if (!ads.length) return ok(`The swipefile is empty${hit ? ` in "${hit.name}"` : ''}. Collections: ${collections.map(c => `${c.name} (${c.ads})`).join(', ')}.`, { collections, ads: [], total: rows.length });
|
|
16127
16127
|
const text = `${rows.length} saved ad(s)${hit ? ` in "${hit.name}"` : ''}${ads.length < rows.length ? ` — showing ${ads.length}` : ''}:\n`
|
|
@@ -16194,6 +16194,10 @@ function memoryNoteVerdict(text) {
|
|
|
16194
16194
|
if (row.platform !== 'creator' || !row.creator) return { content: [{ type: 'text', text: `${key} is a saved ad, not a creator — outreach status only applies to creators (platform "creator").` }], isError: true };
|
|
16195
16195
|
const prev = row.creator.outreach || {};
|
|
16196
16196
|
row.creator.outreach = { status: a.status != null ? a.status : (prev.status || 'new'), note: a.note != null ? String(a.note).slice(0, 2000) : (prev.note || ''), updatedAt: Date.now() };
|
|
16197
|
+
// THE MERGE TIMESTAMP IS savedAt (adapters/sync-merge.js: swipefile.ads ts = savedAt, newer wins, ties go to the
|
|
16198
|
+
// writer). A browser that pushes its cached copy seconds later carries the SAME savedAt and silently overwrote
|
|
16199
|
+
// this edit (measured 2026-09-05). An edit bumps the row's savedAt so every device keeps it.
|
|
16200
|
+
row.savedAt = Date.now();
|
|
16197
16201
|
await writeStore(SWIPE_KEY, s);
|
|
16198
16202
|
const o = row.creator.outreach;
|
|
16199
16203
|
return ok(`@${row.creator.handle || key}: status ${o.status}${o.note ? ` — note: ${o.note}` : ''}.`, { ok: true, key, status: o.status, note: o.note, creator: row.creator });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermoso",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.209",
|
|
4
4
|
"mcpName": "io.github.hermoso-ai/hermoso",
|
|
5
5
|
"description": "AI ad studio and marketing MCP server with 791 tools. Research the ads already running in any market, generate finished image, video and UGC avatar ads, publish and schedule them to your own channels, build and manage the ad campaigns behind them, and read what they achieved. AD PLATFORMS: Meta, Google Ads, TikTok Ads, LinkedIn Ads, Reddit Ads, X Ads, Pinterest Ads, Snapchat Ads, Microsoft Advertising, Apple Search Ads and ChatGPT Ads, plus product feeds in Google Merchant Center. PUBLISHING AND SCHEDULING: Facebook, Instagram, Threads, TikTok, YouTube, X, LinkedIn, Pinterest, Bluesky and Telegram. 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",
|