hermoso 0.1.16 → 0.1.17

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.
Files changed (2) hide show
  1. package/mcp/tools.mjs +36 -0
  2. package/package.json +1 -1
package/mcp/tools.mjs CHANGED
@@ -406,6 +406,41 @@ export function registerTools(server) {
406
406
 
407
407
  // BILLING SURFACE (read → top-up → plan/auto-reload): hermoso_credits (balance) → buy_credits (top-up link) →
408
408
  // billing_status (full picture + your role) → upgrade_plan / set_auto_reload (admin-only, pay-on-Stripe / in-app).
409
+
410
+ // ── FEEDBACK: let the AGENT report a bug or ask for a capability we don't have ────────────────────────────────
411
+ // Dave 2026-07-26: someone driving Hermoso from OpenClaw/Claude/Cursor hits a bug or a missing capability mid-task.
412
+ // Today that feedback dies in their terminal. These two tools turn the agent itself into the reporter — it already
413
+ // has the exact context (what it tried, what came back), which is better than anything a human would retype later.
414
+ // Both just email the team. Free, no credits.
415
+ server.registerTool('report_bug', {
416
+ title: 'Report a bug',
417
+ description: "Report a bug in Hermoso to the team. Use this when something in Hermoso genuinely misbehaves — a tool errors unexpectedly, returns a wrong or malformed result, a render comes back broken, or documented behaviour doesn't match what happened. Include what you were trying to do, the exact tool call and arguments, and what came back. Do NOT use it for out-of-credits, a policy refusal, or a missing capability (use request_feature for that). Free, no credits.",
418
+ inputSchema: {
419
+ summary: z.string().describe('one-line summary of the bug'),
420
+ details: z.string().describe('what you were doing, the tool + arguments you called, what you expected, and what actually happened (paste the exact error)'),
421
+ severity: z.enum(['low', 'medium', 'high']).optional().describe('high = blocks the task or loses paid work; medium = wrong output but workable; low = cosmetic'),
422
+ },
423
+ outputSchema: { ok: z.boolean().optional(), message: z.string().optional() },
424
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
425
+ }, wrap(async ({ summary, details, severity }) => {
426
+ const d = await apiPost('/api/feedback/report', { kind: 'bug', summary, details, severity: severity || 'medium' });
427
+ return ok(d.message || 'Reported — thanks. The team gets this by email with your account attached.', d);
428
+ }));
429
+
430
+ server.registerTool('request_feature', {
431
+ title: 'Request a feature',
432
+ description: "Ask the Hermoso team for a capability that doesn't exist yet. Use this when you need something Hermoso genuinely can't do — an unsupported platform or channel, a missing model, an export format, a tool that would have completed the user's task but isn't available. Say what the user was trying to achieve, not just the feature name — the use case is what gets built. Free, no credits.",
433
+ inputSchema: {
434
+ summary: z.string().describe('one line: the capability you need'),
435
+ details: z.string().describe("what the user was actually trying to achieve, why the current tools couldn't do it, and what you'd expect the capability to do"),
436
+ },
437
+ outputSchema: { ok: z.boolean().optional(), message: z.string().optional() },
438
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
439
+ }, wrap(async ({ summary, details }) => {
440
+ const d = await apiPost('/api/feedback/report', { kind: 'feature', summary, details });
441
+ return ok(d.message || 'Sent — thanks. The team reads every one of these.', d);
442
+ }));
443
+
409
444
  server.registerTool('billing_status', {
410
445
  title: 'Billing status',
411
446
  description: "Show this account's billing at a glance: current plan (id + label + monthly price), credit balance, whether auto-reload is on, whether a card is on file, and whether YOU (this key) have ADMIN rights to change billing. Read-only, free. Call it before upgrade_plan / set_auto_reload to know what's possible — members have read-only billing.",
@@ -780,6 +815,7 @@ export function registerTools(server) {
780
815
  budgetResourceName: z.string().optional().describe('reuse an existing budget instead of creating one'),
781
816
  channelType: z.enum(['SEARCH', 'DISPLAY']).optional().describe('default SEARCH'),
782
817
  searchPartners: z.boolean().optional().describe('SEARCH only — also serve on Google search partners (default false)'),
818
+ dryRun: z.boolean().optional().describe('validate the config against Google without creating anything — proves the account accepts writes and that the fields are valid. Nothing is written and no budget is consumed'),
783
819
  loginCustomerId: z.string().optional().describe('manager id if operating through an MCC'),
784
820
  },
785
821
  outputSchema: { ok: z.boolean().optional(), campaignResourceName: z.string().optional(), campaignId: z.string().optional(), status: z.string().optional(), budgetResourceName: z.string().optional() },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hermoso",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "mcpName": "io.github.hermoso-ai/hermoso",
5
5
  "description": "Generate finished VIDEO ADS, image ads and UGC avatar ads for any brand with AI — and spy on competitor ads across the Meta, Google and LinkedIn ad libraries plus TikTok/Instagram/YouTube organic. MCP server, CLI and Claude skills for Hermoso, the AI ad studio: brand onboarding, 30+ image/video models, finished-ad pipeline (script, voiceover, music, brand end card), ad scoring and competitor teardowns.",
6
6
  "type": "module",