hermoso 0.1.206 → 0.1.207

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/README.md CHANGED
@@ -5,7 +5,7 @@ scripts. Research the ads already winning in a market, generate finished image &
5
5
  composited in, copy + CTA included), publish them to your own social channels, and build & manage the ad
6
6
  campaigns behind them — all over [MCP](https://modelcontextprotocol.io) tools, a CLI, or installable Claude skills.
7
7
 
8
- **790 tools.** `tools/list` is always the authoritative set; `hermoso_capabilities` (free) returns the live model
8
+ **791 tools.** `tools/list` is always the authoritative set; `hermoso_capabilities` (free) returns the live model
9
9
  catalog with exact per-render credit costs plus the full capability map.
10
10
 
11
11
  **What it connects to.** Ad platforms: Meta, Google Ads, TikTok Ads, LinkedIn Ads, Reddit Ads, X Ads,
@@ -171,7 +171,7 @@ block entirely if you signed in above; it is there for CI, where the process can
171
171
 
172
172
  Then ask your agent: *“Generate an image ad with Hermoso.”*
173
173
 
174
- ### What the 790 tools cover
174
+ ### What the 791 tools cover
175
175
 
176
176
  **Ad spy / research** — `find_competitors`, `competitor_teardown`, `pull_competitor_ads`, `research_ads`; the
177
177
  Meta / Google / LinkedIn ad libraries (`search_meta_ads`, `search_google_ads`, `search_linkedin_ads`); organic
package/mcp/tools.mjs CHANGED
@@ -16161,7 +16161,7 @@ function memoryNoteVerdict(text) {
16161
16161
  const key = swipeKeyOf(it);
16162
16162
  const ex = s.ads.find(x => x && x.key === key);
16163
16163
  if (ex) { if (ex.collectionId !== col.id) moved++; ex.collectionId = col.id; continue; }
16164
- s.ads.push({ key, collectionId: col.id, advertiser: String(it.advertiser || '').slice(0, 120), title: String(it.title || '').slice(0, 300), body: String(it.body || '').slice(0, 2000), image: String(it.image || ''), video: String(it.video || ''), link: String(it.link || it.url || ''), platform: String(it.platform || '').slice(0, 40), savedAt: Date.now() });
16164
+ s.ads.push({ key, collectionId: col.id, advertiser: String(it.advertiser || '').slice(0, 120), title: String(it.title || '').slice(0, 300), body: String(it.body || '').slice(0, 2000), image: String(it.image || ''), video: String(it.video || ''), link: String(it.link || it.url || ''), platform: String(it.platform || '').slice(0, 40), savedAt: Date.now() , ...(it.platform === 'creator' && it.creator && typeof it.creator === 'object' ? { creator: it.creator } : {}) });
16165
16165
  saved++;
16166
16166
  }
16167
16167
  s.activeId = col.id;
@@ -16169,6 +16169,36 @@ function memoryNoteVerdict(text) {
16169
16169
  return ok(`${saved} ad(s) saved${moved ? `, ${moved} moved` : ''} into “${col.name}”${created ? ' (new collection)' : ''} — it’s on the workspace swipefile now (list_swipefile to read it back).`, { ok: true, collection: col.name, collectionId: col.id, saved, moved, total: s.ads.length });
16170
16170
  }));
16171
16171
 
16172
+
16173
+ // ── SAVED CREATORS: outreach status + notes (2026-09-05, Dave: "parity with dedicated tools"). A creator saved by
16174
+ // find_creators → save_to_swipefile carries `creator`; this writes the OUTREACH state onto that row so the whole
16175
+ // team — web and agent — sees who has been contacted, who replied, who is booked. One row, one field, never a
16176
+ // second store: the swipefile is already synced, tombstoned and union-merged.
16177
+ server.registerTool('update_saved_creator', {
16178
+ title: 'Update a saved creator (outreach status, note)',
16179
+ description: 'Set the OUTREACH STATUS and/or a NOTE on a creator already saved in the swipefile (find_creators → save_to_swipefile, or the ♥ on a creator card). Status is one of new | contacted | replied | booked | passed. The note is free text (deal terms, rate, what was sent). Reads back the updated row. Use list_swipefile to find the key. Free.',
16180
+ inputSchema: {
16181
+ key: z.string().describe("the saved row's key from list_swipefile, e.g. tiktok:handle"),
16182
+ status: z.enum(['new', 'contacted', 'replied', 'booked', 'passed']).optional(),
16183
+ note: z.string().max(2000).optional().describe('replaces the existing note; pass "" to clear it'),
16184
+ },
16185
+ outputSchema: { ok: z.boolean().optional(), key: z.string().optional(), status: z.string().optional(), note: z.string().optional(), creator: z.any().optional() },
16186
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
16187
+ }, wrap(async (a) => {
16188
+ const key = String(a.key || '').trim();
16189
+ if (!key) return { content: [{ type: 'text', text: 'Pass the saved creator key (from list_swipefile).' }], isError: true };
16190
+ if (a.status == null && a.note == null) return { content: [{ type: 'text', text: 'Pass a status and/or a note.' }], isError: true };
16191
+ const s = await readSwipe();
16192
+ const row = s.ads.find(x => x && x.key === key);
16193
+ if (!row) return { content: [{ type: 'text', text: `No saved row with key ${key}. list_swipefile shows every key.` }], isError: true };
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
+ const prev = row.creator.outreach || {};
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
+ await writeStore(SWIPE_KEY, s);
16198
+ const o = row.creator.outreach;
16199
+ 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 });
16200
+ }));
16201
+
16172
16202
  // ── PLAYBOOKS — the "what's working + the plays to run" cards, distinct from the swipefile's raw creative. Same
16173
16203
  // server-synced store seam (`heist.playbooks.v1`, union-merged by id in adapters/sync-merge.js); the web app has a
16174
16204
  // Playbooks tab that lists, runs and deletes them, and the Studio chat can save one. Headlessly there was no way to
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "hermoso",
3
- "version": "0.1.206",
3
+ "version": "0.1.207",
4
4
  "mcpName": "io.github.hermoso-ai/hermoso",
5
- "description": "AI ad studio and marketing MCP server with 790 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.",
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",
7
7
  "bin": {
8
8
  "hermoso": "bin/hermoso.mjs"