hermoso 0.1.272 → 0.1.273

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/bin/hermoso.mjs CHANGED
@@ -109,7 +109,7 @@ async function main() {
109
109
  case 'capabilities': case 'caps': {
110
110
  const d = await api.apiGet('/api/generate/status');
111
111
  if (flags.json) return console.log(JSON.stringify(d, null, 2));
112
- console.log('IMAGE models:'); (d.options?.image?.models || []).forEach(m => console.log(` ${m.id.padEnd(18)} ${m.label} · ${m.credits}cr${m.best ? ' ★best' : ''}`));
112
+ console.log('IMAGE models:'); (d.options?.image?.models || []).forEach(m => console.log(` ${m.id.padEnd(18)} ${m.label} · ${m.credits}cr${m.best ? ' ★best' : ''}${m.aspectRatios?.length ? ` · aspect ${m.aspectRatios.join(' ')}` : ''}`));
113
113
  console.log('VIDEO models:'); (d.options?.video?.models || []).forEach(m => console.log(` ${m.id.padEnd(18)} ${m.label} · ${(m.durations || []).join('/')}s`));
114
114
  console.log(`flags: canEdit=${d.canEdit} canAvatar=${d.canAvatar} canPublish=${d.canPublish}`);
115
115
  console.log(`recipes: ${(d.recipes || []).map(r => r.id).join(', ')}`);
package/mcp/tools.mjs CHANGED
@@ -3484,7 +3484,7 @@ function buildTools(rawServer, opts = {}, sink = null) {
3484
3484
  _meta: openaiMeta(CAPABILITIES_URI, 'Loading the model catalog…', 'Model catalog ready'),
3485
3485
  }, wrap(async () => {
3486
3486
  const d = await apiGet('/api/generate/status');
3487
- const img = (d.options?.image?.models || []).map(m => `${m.id} (${m.label}, ${m.credits}cr${m.refs ? `, ≤${m.refs.max} reference images` : ''}${m.creditsBySize && Object.keys(m.creditsBySize).length > 1 ? `, imageSize ${Object.entries(m.creditsBySize).map(([s, c]) => `${s}=${c}cr`).join(' ')}` : m.hiRes ? ', 2K' : ''}${m.best ? ', best' : ''})`).join('; ');
3487
+ const img = (d.options?.image?.models || []).map(m => `${m.id} (${m.label}, ${m.credits}cr${m.refs ? `, ≤${m.refs.max} reference images` : ''}${m.creditsBySize && Object.keys(m.creditsBySize).length > 1 ? `, imageSize ${Object.entries(m.creditsBySize).map(([s, c]) => `${s}=${c}cr`).join(' ')}` : m.hiRes ? ', 2K' : ''}${Array.isArray(m.aspectRatios) && m.aspectRatios.length ? `, aspect ${m.aspectRatios.join(' ')}` : ''}${m.best ? ', best' : ''})`).join('; ');
3488
3488
  // durations + per-duration credits MATTER: without them agents assume the generic "AI video caps at 8-10s"
3489
3489
  // prior and wrongly steer users to stitching (a real Claude.ai session did exactly that on a 15s ad)
3490
3490
  const vid = (d.options?.video?.models || []).map(m => `${m.id} (${m.label}: one continuous clip of ${(m.durations || []).map(x => `${x}s=${m.credits?.[x] ?? '?'}cr`).join(' ')}${m.audio ? ', native audio' : ', silent'}${m.refs ? `, ${m.refs.max} reference image${m.refs.max === 1 ? '' : 's'}${m.refs.required ? ' (required — image-to-video only)' : ''}` : ''}${m.resolutions ? `, resolutions ${m.resolutions.join('/')}` : ''}${Array.isArray(m.cameraMoves) && m.cameraMoves.length ? `, camera moves ${m.cameraMoves.map(c => c.id).join('/')} (generate_video cameraMove, or your own cameraTrajectory keyframes)` : ''}${m.best ? ', best' : ''})`).join('; ');
@@ -16883,7 +16883,7 @@ function buildTools(rawServer, opts = {}, sink = null) {
16883
16883
  refImages: z.array(z.string()).optional().describe('local file paths or URLs of product/logo references to composite in. ON THE POSE MODELS — any row hermoso_capabilities marks `needsRefs` with a `refsMax`, such as putting your product in someone’s hands or a virtual try-on — THE ORDER IS THE CONTRACT AND IT IS NOT A COMPOSITE: refImages[0] is the PERSON photo, and the rest (up to `refsMax` minus one) are the product or garment photos. Reversed, you get the product wearing the person. A 4th product is dropped and the reply says so.'),
16884
16884
  useBrand: z.boolean().optional().describe('default true: with no refImages, the server hydrates the SAVED brand’s product/logo references so the output lands on-brand; pass false for a pure prompt-only render'),
16885
16885
  raw: z.boolean().optional().describe('RAW MODEL ACCESS: run the caller’s prompt on the named model with no Hermoso adjustments at all — the prompt reaches the provider byte-identical (no hex-to-colour-name rewrite, no prepended fidelity preamble) and NO saved-brand product photos are attached, so the model you name is the model that renders. Use it to drive the raw catalog; leave it off for an on-brand ad. Billing, the durable Library landing and per-model validation are unchanged.'),
16886
- aspectRatio: z.string().optional().describe("e.g. '1:1', '9:16', '16:9'"),
16886
+ aspectRatio: z.string().optional().describe("e.g. '1:1', '9:16', '16:9', '4:5'. Each model draws its own list (hermoso_capabilities prints it per model, e.g. Nano Banana 2 goes to 1:8 and 8:1); a ratio the chosen model cannot draw is refused before anything is charged"),
16887
16887
  model: z.string().optional().describe('image model id from hermoso_capabilities. A model whose `refs.mode` is "edit" there (gpt-image-2.5) takes your refImages on ITS OWN editor, up to its `refs.max`, instead of the default compositor'),
16888
16888
  imageSize: z.string().optional().describe('pixel-size preset for models that support it: 1K/2K, and 4K on the models hermoso_capabilities lists with a 4K imageSize price (a 4K ask on any other model is refused, free) — omit for the default'),
16889
16889
  mask: z.string().optional().describe('MASKED EDIT — change ONE region of an image and keep the rest: a local path or URL of a mask image for refImages[0] (the image being edited). Either convention works and the reply says which it read: TRANSPARENT pixels = change, or, on a mask with no transparency, WHITE = change and black = keep. Any size; it is scaled to the image. The mask GUIDES the edit rather than stencilling it: the new content can blend a little past its edge. Runs on the model hermoso_capabilities marks `refs.mask` (gpt-image-2.5): leave `model` empty or name that one — any other named model is refused, free. Needs refImages; the result keeps the source image\'s own frame, so aspectRatio is not applied.'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hermoso",
3
- "version": "0.1.272",
3
+ "version": "0.1.273",
4
4
  "mcpName": "io.github.hermoso-ai/hermoso",
5
5
  "description": "Marketing on autopilot, run from your own AI agent. 856 tools. Publishing, scheduling, ad campaign management, comments, DMs and analytics cost no credits on every plan; credits are only for generating creative and for Ad Spy research. 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",