hermoso 0.1.71 → 0.1.86

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
- **372 tools.** `tools/list` is always the authoritative set; `hermoso_capabilities` (free) returns the live model
8
+ **415 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
  **It is not all-or-nothing.** Research, creation, publishing/scheduling and ads management are four *independent*
@@ -53,7 +53,7 @@ Cursor / Codex — add to `mcp.json` (Codex uses the TOML equivalent):
53
53
 
54
54
  Then ask your agent: *“Generate an image ad with Hermoso.”*
55
55
 
56
- ### What the 372 tools cover
56
+ ### What the 415 tools cover
57
57
 
58
58
  **Ad spy / research** — `find_competitors`, `competitor_teardown`, `pull_competitor_ads`, `research_ads`; the
59
59
  Meta / Google / LinkedIn ad libraries (`search_meta_ads`, `search_google_ads`, `search_linkedin_ads`); organic
@@ -90,10 +90,12 @@ publish). `schedule_post` / `list_scheduled` / `cancel_scheduled` give you one c
90
90
  *X posting bills credits per API call (X charges per request); a post containing a link costs 13× one without.*
91
91
 
92
92
  **Run the ads** — full campaign trees, built paused and read back before anything is reported, with every spend
93
- change confirm-gated, on **Meta**, **Google Ads**, **LinkedIn Ads**, **Reddit Ads**, **Pinterest Ads**,
94
- **Microsoft Advertising** and **ChatGPT Ads** (OpenAI's Advertiser API). Each has list + report + create + budget/status tools
93
+ change confirm-gated, on **ten** platforms: **Meta**, **Google Ads**, **LinkedIn Ads**, **Reddit Ads**,
94
+ **Pinterest Ads**, **Microsoft Advertising**, **ChatGPT Ads** (OpenAI's Advertiser API), **X Ads**, **TikTok Ads**
95
+ and **Snapchat Ads**. Each has list + report + create + budget/status tools
95
96
  (e.g. `list_google_ads_campaigns`, `google_ads_report`, `create_google_ads_campaign`, `set_google_ads_budget`,
96
- `set_google_ads_status`). *X Ads are not supported X posting only.*
97
+ `set_google_ads_status`). *Snapchat needs one extra step the others do not: an ad points at a CREATIVE, and every
98
+ Snapchat creative must carry a Public Profile id — build it with `upload_snapchat_ads_creative`.*
97
99
 
98
100
  **Measure what the ads achieved** — Google Analytics 4 closes the loop. Every other connector here reports what an
99
101
  ad *cost*; this is the one that reports what it *did*. `analytics_report` breaks sessions, users, conversions and
@@ -114,8 +116,8 @@ property holds 50 event-scoped ones.*
114
116
 
115
117
  **Workspace & account** — brand workspaces (`list_brands`, `create_brand`, `use_brand`, `update_brand`,
116
118
  `delete_brand` — one account holds many brands, so an agency runs every client through here), memory
117
- (`remember`, `forget`, `list_memory`), custom skills (`save_skill`, `delete_skill`), AI employees
118
- (`save_employee`, `list_employees`, `set_active_employee`), team (`list_team`, `invite_member`, `remove_member`,
119
+ (`remember`, `forget`, `list_memory`), custom skills (`save_skill`, `get_skill`, `list_skills`,
120
+ `delete_skill` — the one library, which absorbed the old AI-Employee personas), team (`list_team`, `invite_member`, `remove_member`,
119
121
  `set_role`), settings (`get_settings`, `update_settings` — including the **language** every ad, script and plan
120
122
  is written in), connectors (`list_connectors`, `list_connector_accounts`, `set_connector_accounts`,
121
123
  `disconnect_connector`), and billing (`hermoso_credits`, `billing_status`, `buy_credits`, `upgrade_plan`,
package/mcp/client.mjs CHANGED
@@ -173,6 +173,15 @@ export async function apiUpload(p, buf, { contentType = 'application/octet-strea
173
173
  const res = await fetch(`${API_BASE}${p}`, { method: 'POST', headers: h, body: buf });
174
174
  return unwrap(res);
175
175
  }
176
+ // Ingest by URL: the SERVER fetches the bytes (SSRF-guarded on every redirect hop) so nothing has to cross this
177
+ // transport. Deliberately no body — /api/upload treats "a body AND a url" as an error rather than picking one.
178
+ export async function apiUploadUrl(p, url, { fileName = '' } = {}) {
179
+ const h = headers({});
180
+ delete h['Content-Type']; // a body-less POST must not claim one; the server sniffs the FETCHED bytes
181
+ if (fileName) h['x-file-name'] = encodeURIComponent(fileName);
182
+ const res = await fetch(`${API_BASE}${p}?url=${encodeURIComponent(url)}`, { method: 'POST', headers: h });
183
+ return unwrap(res);
184
+ }
176
185
 
177
186
  // /api/explore/chat streams Server-Sent-Events; collect to the terminal `done` payload {reply, results, actions}.
178
187
  export async function apiSSE(p, body = {}) {