gooseworks 0.3.14 → 0.3.16
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 +52 -2
- package/dist/auth/attribution.d.ts +14 -0
- package/dist/auth/attribution.d.ts.map +1 -0
- package/dist/auth/attribution.js +37 -0
- package/dist/auth/attribution.js.map +1 -0
- package/dist/auth/oauth-server.d.ts +4 -4
- package/dist/auth/oauth-server.d.ts.map +1 -1
- package/dist/auth/oauth-server.js +8 -8
- package/dist/auth/oauth-server.js.map +1 -1
- package/dist/commands/call.d.ts.map +1 -1
- package/dist/commands/call.js +6 -5
- package/dist/commands/call.js.map +1 -1
- package/dist/commands/install.js +1 -1
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/log.d.ts +15 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +121 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/login.d.ts +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +10 -4
- package/dist/commands/login.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/skills/master-skill.d.ts.map +1 -1
- package/dist/skills/master-skill.js +228 -143
- package/dist/skills/master-skill.js.map +1 -1
- package/package.json +1 -1
- package/skills/goose-ads/SKILL.md +106 -102
- package/skills/goose-product-photos/SKILL.md +105 -0
- package/skills/goose-video/SKILL.md +24 -1
- package/skills/gooseworks/SKILL.md +98 -40
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;AA4BA,wCAMC;AAWD,
|
|
1
|
+
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;AA4BA,wCAMC;AAWD,sDAwRC;AAiBD,0DA0UC;AAcD,8DA2bC;AA9kCD,oDAAoD;AACpD,SAAgB,cAAc;IAC5B,OAAO;QACL,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE;QACxD,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE;QACzD,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE;KAC9D,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsRR,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,uBAAuB;IACrC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwUR,CAAC;AACF,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,yBAAyB;IACvC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAybR,CAAC;AACF,CAAC"}
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
name: goose-ads
|
|
3
3
|
slug: goose-ads
|
|
4
4
|
description: >
|
|
5
|
-
GooseWorks ads skill — create, edit, AND analyze ad creative.
|
|
6
|
-
|
|
5
|
+
GooseWorks ads skill — create, edit, AND analyze ad creative. Turn an approved source ad
|
|
6
|
+
into a branded ad for the user's product, edit/re-roll an existing creative,
|
|
7
7
|
research a brand for ads, OR analyze ad performance (Meta/Google campaign diagnostics,
|
|
8
8
|
creative fatigue, CAC & lead quality, competitor ad intelligence, ad angles & hooks). Use
|
|
9
9
|
when the user says "remix this ad", references a static ad template id/slug, asks to "make
|
|
@@ -12,7 +12,7 @@ description: >
|
|
|
12
12
|
app uses) — credits are reserved and billed server-side. Analytics recipes are fetched from
|
|
13
13
|
goose-skills on demand.
|
|
14
14
|
category: ads
|
|
15
|
-
version: 2.
|
|
15
|
+
version: 2.4.0
|
|
16
16
|
author: GooseWorks
|
|
17
17
|
tags: [gooseworks, ads, remix, static-ad, brand, creative, image, analytics, meta-ads, performance]
|
|
18
18
|
---
|
|
@@ -22,7 +22,7 @@ tags: [gooseworks, ads, remix, static-ad, brand, creative, image, analytics, met
|
|
|
22
22
|
The GooseWorks ads skill. Two jobs:
|
|
23
23
|
|
|
24
24
|
1. **Create / edit ad creative** — a **thin wrapper** over the backend's single generation
|
|
25
|
-
workflow. You pick the brand +
|
|
25
|
+
workflow. You pick the brand + approved source ad(s) and submit ONE batch; the **backend** runs the
|
|
26
26
|
whole pipeline (compose → generate → persist → judge), reserves and bills credits, and
|
|
27
27
|
stores the renders. You do NOT generate images, call FAL, manage render rows, or upload
|
|
28
28
|
files — those are gone. This is the exact same workflow the GooseWorks ads app uses, so the
|
|
@@ -46,74 +46,63 @@ no HTTP/file fallback — the REST ad endpoints are session-cookie-only and reje
|
|
|
46
46
|
message and stop) and bills only the images that actually complete. Call
|
|
47
47
|
`estimate_remix_batch` first to tell the user the cost; `gooseworks credits` shows balance.
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## Live MCP contract — inspect it before asking
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
The currently registered MCP tool schemas are the source of truth for inputs, supported choices,
|
|
52
|
+
and defaults. Do not copy an exhaustive input list from this skill or rely on remembered fields.
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
- `ratios`: **["4:5"]** (Meta feed vertical)
|
|
56
|
-
- `engine`: **"gpt_image_2"**
|
|
57
|
-
- `quality`: **"medium"**
|
|
58
|
-
- `preserve_source_styling`: **ASK the user** — "Keep original" (the template's own
|
|
59
|
-
colours/fonts → `preserve_source_styling: true`) vs "Match brand" (restyle to the brand
|
|
60
|
-
palette/fonts → `preserve_source_styling: false`). This mirrors the app's Styling control.
|
|
61
|
-
**The default is "Keep original"** — if the user doesn't answer or doesn't care, send `true`.
|
|
54
|
+
Before each tool call:
|
|
62
55
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
1. Inspect the live schema for the tool you are about to use.
|
|
57
|
+
2. Fill required inputs already known from the Brand Kit, selected source, or conversation.
|
|
58
|
+
3. Ask the user only for required inputs that cannot be inferred and for choices that materially
|
|
59
|
+
change the result. Do not turn every optional field into a questionnaire.
|
|
60
|
+
4. Omit unspecified optional settings so the backend applies its current app defaults.
|
|
61
|
+
5. If the live schema conflicts with this workflow, follow the live schema and report the drift
|
|
62
|
+
with `log_cli_event`.
|
|
66
63
|
|
|
67
64
|
## The generation tools (the new, single-workflow surface)
|
|
68
65
|
|
|
69
|
-
- `submit_remix_batch
|
|
70
|
-
|
|
71
|
-
that makes ads.** `items` is `[{ template_id, variants?, ratios? }]` (≤20 templates).
|
|
66
|
+
- `submit_remix_batch` — **the one call that makes ads.** Inspect its live schema and supply
|
|
67
|
+
the required brand/source inputs plus any choices the user explicitly made.
|
|
72
68
|
Returns the batch with a `links` block (`brand_url` + per-creative `app_url`). If the brand's
|
|
73
69
|
research isn't finished yet the batch comes back `status: "queued"` — it auto-runs the moment
|
|
74
70
|
research completes; tell the user it'll appear shortly, don't error.
|
|
75
|
-
- `estimate_remix_batch
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
resolve (submit would 404 on it); don't quote a cost that silently dropped a bad id.
|
|
79
|
-
- `get_remix_batch { batch_id }` — poll status. Returns each creative with its renders and
|
|
71
|
+
- `estimate_remix_batch` — cost preview. Reserves nothing. Use it to quote the cost first and
|
|
72
|
+
check whether every selected source resolved before submitting.
|
|
73
|
+
- `get_remix_batch` — poll status. Returns each creative with its renders and
|
|
80
74
|
`completed`/`failed`/`pending` counts, plus `links`. A creative is done when its `pending` is 0
|
|
81
75
|
— NOT when `current_render_url` is set (during a regenerate that field still points at the prior
|
|
82
76
|
image). Each render carries `age_seconds` (since queued) and `elapsed_seconds` (time generating):
|
|
83
77
|
use them to tell a slow-but-healthy render from a stuck one. A render only failed when its
|
|
84
78
|
`status` is `"failed"` — never assume a stall and re-submit, that double-bills.
|
|
85
|
-
- `list_brand_creatives
|
|
79
|
+
- `list_brand_creatives` — the brand's gallery feed (newest
|
|
86
80
|
first) + `brand_url`. Alternative poll target; also use to show everything made for a brand.
|
|
87
|
-
- `surprise_me_templates
|
|
88
|
-
|
|
89
|
-
|
|
81
|
+
- `surprise_me_templates` — the **"Surprise me" recommender**. Picks
|
|
82
|
+
remixable Community creations (SAME logic as the web /create "Surprise me" button), shuffled
|
|
83
|
+
so picks stay fresh. It does not use the retired curated third-party catalog.
|
|
90
84
|
Returns the picked templates (id, slug, title, image, ratio) AND a ready-to-open `create_url`
|
|
91
85
|
(the /create page with `cli=true` and the picks pre-selected). This is how you recommend
|
|
92
86
|
templates — do NOT hand-pick from the raw catalog yourself (see "Picking templates" below).
|
|
93
|
-
- `regenerate_creative
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- `set_creative_feedback { render_id, rating?, comment?, reasons? }` — record the user's reaction
|
|
99
|
-
to a generated image (the SAME happy/neutral/sad + comment + reason chips the app captures). Use
|
|
100
|
-
it whenever the user reacts ("love this one" / "the logo is wrong"). `render_id` is a RENDER id
|
|
101
|
-
from `get_remix_batch` / `list_brand_creatives`, not a project/batch id. `reasons` are quick
|
|
102
|
-
chips (wrong_product, brand_or_logo_wrong, off_brand, text_garbled, weak_copy, ai_or_distorted).
|
|
87
|
+
- `regenerate_creative` — edit or re-roll one existing creative through the same pipeline.
|
|
88
|
+
Inspect the live schema to select the supported mode and required source inputs. Returns a
|
|
89
|
+
single-item batch; poll it with `get_remix_batch`.
|
|
90
|
+
- `set_creative_feedback` — record the user's reaction to a generated image. Use it whenever
|
|
91
|
+
the user reacts; inspect the schema for the current rating and reason choices.
|
|
103
92
|
|
|
104
93
|
### Plan mode — review the plan BEFORE generating (optional)
|
|
105
94
|
|
|
106
95
|
For users who want to approve each ad's plan before spending credits (the app's "Plan it" flow):
|
|
107
96
|
|
|
108
|
-
-
|
|
97
|
+
- Use the approval option exposed by `submit_remix_batch` — it composes each creative's plan and PAUSES.
|
|
109
98
|
**No credits are reserved and no image renders** until you approve.
|
|
110
|
-
- `list_ad_approvals
|
|
99
|
+
- `list_ad_approvals` — poll this. While a creative is
|
|
111
100
|
`composing`, wait; once `awaiting_approval`, show its `plan` (composed prompt + refs + quality)
|
|
112
101
|
to the user.
|
|
113
|
-
- `revise_ad_plan
|
|
102
|
+
- `revise_ad_plan` — recompose from a chat steer, still
|
|
114
103
|
free. Poll `list_ad_approvals` until it's `awaiting_approval` again.
|
|
115
|
-
- `approve_ad_plan
|
|
116
|
-
|
|
104
|
+
- `approve_ad_plan` — approve one creative or the whole batch using the live schema.
|
|
105
|
+
**This is the step that reserves credits and renders.** Then poll
|
|
117
106
|
`get_remix_batch` and hand back links as usual.
|
|
118
107
|
|
|
119
108
|
Only offer plan mode when the user asks to review/approve first — the default path generates
|
|
@@ -121,19 +110,23 @@ immediately.
|
|
|
121
110
|
|
|
122
111
|
## Reading the brand & picking inputs (still MCP, read-only)
|
|
123
112
|
|
|
124
|
-
- `get_brand_kit
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
113
|
+
- `get_brand_kit` — read the canonical brand context and available products/assets.
|
|
114
|
+
- `list_ad_brands` / `get_ad_brand` — find and fetch the active brand.
|
|
115
|
+
- `list_user_ad_templates` — list the org's own uploads and
|
|
116
|
+
imported ads. Prefer `relationship: "self"` when the user wants to reuse their own ads;
|
|
117
|
+
`relationship: "competitor"` is research/inspiration, never proof that the user owns the ad.
|
|
118
|
+
- `search_ad_templates` — search remixable Community generations. The
|
|
119
|
+
retired curated third-party catalog is not returned.
|
|
120
|
+
- `get_static_ad_template` — resolve a source already owned by
|
|
121
|
+
the org, including an own upload or a snapshotted Community creative. It does not resolve the
|
|
122
|
+
retired curated third-party catalog.
|
|
123
|
+
- `remix_community_ad` — turn a selected Community creative into a private remix source before
|
|
124
|
+
submitting it. A Community ad id is an `ad_project` id, not a
|
|
133
125
|
template id. Call this FIRST to snapshot it into a private template, then use the returned
|
|
134
126
|
template `id` in `items`.
|
|
135
|
-
- `create_user_ad_template
|
|
136
|
-
|
|
127
|
+
- `create_user_ad_template` — upload a source image as a private template. Answer any
|
|
128
|
+
ownership/rights input only from the user's explicit confirmation. Never claim rights for a
|
|
129
|
+
competitor ad or an image found online.
|
|
137
130
|
- `get_ad_project` / `append_project_message` — inspect a creative / leave a note on its thread.
|
|
138
131
|
|
|
139
132
|
## Keep the brand kit in sync — reconcile, then update (ASK first)
|
|
@@ -144,7 +137,7 @@ tagline, audience, voice, a product's name/price/description, "our logo is X", "
|
|
|
144
137
|
anymore", a new product photo — treat it as a possible kit update, don't just use it for this one
|
|
145
138
|
ad and forget it:
|
|
146
139
|
|
|
147
|
-
1. **Check it against the kit.** `get_brand_kit
|
|
140
|
+
1. **Check it against the kit.** Call `get_brand_kit` for the active brand and see whether what the user said
|
|
148
141
|
matches, is missing from, or contradicts the kit.
|
|
149
142
|
2. **If it's already in the kit and matches** — nothing to do; proceed.
|
|
150
143
|
3. **If it's new or different — ASK before writing.** Confirm in one line: *"Want me to update
|
|
@@ -152,65 +145,72 @@ ad and forget it:
|
|
|
152
145
|
asked you to change the brand). Don't silently mutate the kit, and don't nag on trivia.
|
|
153
146
|
4. **Persist with the write tools** (partial — only the fields you pass are touched; each edit is
|
|
154
147
|
recorded as a user override that later re-research won't clobber):
|
|
155
|
-
- `update_brand_kit
|
|
156
|
-
|
|
157
|
-
- `
|
|
158
|
-
|
|
159
|
-
reference photos.
|
|
148
|
+
- `update_brand_kit` — structured brand fields.
|
|
149
|
+
- `upsert_brand_product` / `delete_brand_product` — products.
|
|
150
|
+
- `add_brand_product_image` / `remove_brand_reference_image` — product and reference photos.
|
|
151
|
+
Inspect each live schema and send only the fields needed for the confirmed change.
|
|
160
152
|
5. **Confirm what changed** and continue the task. (Logo, colors, and fonts are owned by the
|
|
161
153
|
backend research pass — prefer `update_ad_brand` / the research flow for those, not free text.)
|
|
162
154
|
|
|
163
155
|
This is the parity gap the app closes in-product: a brand fact the user gives mid-task should be
|
|
164
156
|
able to flow back into the kit — with their ok — instead of being lost.
|
|
165
157
|
|
|
166
|
-
## Picking
|
|
158
|
+
## Picking source ads — use approved sources, not the retired catalog
|
|
167
159
|
|
|
168
160
|
When the user wants to make ads but has NOT named a specific template (id/slug/Community
|
|
169
161
|
ad/upload), do NOT silently browse the raw catalog and hand-pick for them. Instead run this
|
|
170
162
|
short ask flow — it mirrors the web app and keeps the human in the loop:
|
|
171
163
|
|
|
172
164
|
1. **Ask what kind of ads they want** — the angle/offer/theme/season, the vibe, and which
|
|
173
|
-
product from the brand kit to feature. This shapes both the
|
|
165
|
+
product from the brand kit to feature. This shapes both the source choice and your steering
|
|
174
166
|
`prompt`. Keep it to one or two quick questions.
|
|
175
|
-
2. **Ask how to pick
|
|
176
|
-
- **
|
|
177
|
-
|
|
167
|
+
2. **Ask how to pick a source: their own ads, Community, upload, or "Surprise me".**
|
|
168
|
+
- **Their own ads** → use `list_user_ad_templates` to load the active brand's own sources and
|
|
169
|
+
let them choose from the results.
|
|
170
|
+
- **Community** → `search_ad_templates`, let them choose, then call `remix_community_ad`
|
|
171
|
+
before submitting.
|
|
172
|
+
- **Upload** → upload through the workspace and call `create_user_ad_template`. If its live
|
|
173
|
+
schema requires an ownership or permission answer, only supply it after explicit confirmation.
|
|
174
|
+
- **Surprise me** (they want you/the app to pick) → call `surprise_me_templates` for the active
|
|
175
|
+
brand and hand the user the returned `create_url`.
|
|
178
176
|
It opens /create in **CLI mode** with the picks pre-selected, a preview modal, and the
|
|
179
177
|
**copyable remix prompt at the bottom** (in place of the Generate input). They can swap
|
|
180
178
|
picks and copy that prompt. If they'd rather you "just make them" without reviewing in the
|
|
181
179
|
app, you MAY submit the `surprise_me_templates` picks directly (skip to submit).
|
|
182
|
-
- **
|
|
180
|
+
- **Browse in the app** → hand the user this URL, with the
|
|
183
181
|
active brand's slug filled in:
|
|
184
182
|
`https://make.gooseworks.ai/create?brand=<brand-slug>&cli=true`
|
|
185
183
|
In CLI mode the app shows the copyable remix prompt at the bottom (dismissable / switchable
|
|
186
|
-
back to the UI composer). They browse
|
|
187
|
-
3. **
|
|
188
|
-
4. **Close the loop.** When the user **pastes back the copyable remix prompt** from the app
|
|
184
|
+
back to the UI composer). They browse the available own/Community sources and copy the prompt.
|
|
185
|
+
3. **Close the loop.** When the user **pastes back the copyable remix prompt** from the app
|
|
189
186
|
(it names the brand + the templates they chose), THAT is your cue to generate: resolve the
|
|
190
|
-
named
|
|
187
|
+
named source(s), inspect `submit_remix_batch`, and collect only its unresolved required inputs.
|
|
191
188
|
|
|
192
|
-
If the user already named
|
|
193
|
-
|
|
189
|
+
If the user already named an owned source (id/slug), a Community ad, or an upload, skip the source
|
|
190
|
+
choice. Competitor ads may inform the angle or structure, but describe them as inspiration, never
|
|
191
|
+
claim ownership, and never attest rights for the user.
|
|
194
192
|
|
|
195
193
|
## Workflow — make ads from a template
|
|
196
194
|
|
|
197
|
-
1. **Resolve the brand.** `list_ad_brands` by name/site
|
|
195
|
+
1. **Resolve the brand.** Use `list_ad_brands` by name/site, then call `get_brand_kit` for the
|
|
196
|
+
selected brand. If the
|
|
198
197
|
kit's `researchStatus` isn't `complete`, you can still submit (the batch queues and runs when
|
|
199
198
|
research finishes) — just tell the user. Use the kit to pick `product_name` (a real entry from
|
|
200
199
|
`products[]`, not a guess) and, if the user supplied product photos, `reference_image_urls`.
|
|
201
|
-
2. **Pick the
|
|
202
|
-
|
|
200
|
+
2. **Pick the source ad(s) via the ask flow above.** Once you have concrete ids:
|
|
201
|
+
call `get_static_ad_template` for each.
|
|
203
202
|
For a Community ad, `remix_community_ad` first; for an uploaded image, `create_user_ad_template`
|
|
204
203
|
first.
|
|
205
204
|
3. **(Optional) Craft the steering prompt.** The `prompt` is OPTIONAL — this is where the skill
|
|
206
205
|
adds value: turn the user's intent (from step 1) into a concise steering note (e.g. tone,
|
|
207
206
|
season, emphasis). Don't over-specify; the backend pipeline + brand kit handle palette, fonts,
|
|
208
207
|
product swap.
|
|
209
|
-
4. **
|
|
210
|
-
5. **Submit ONE batch.** `submit_remix_batch
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
6. **Poll until done.** `get_remix_batch
|
|
208
|
+
4. **Quote the cost.** Inspect and call `estimate_remix_batch`, then tell the user.
|
|
209
|
+
5. **Submit ONE batch.** Inspect the current `submit_remix_batch` schema, fill known required
|
|
210
|
+
inputs, ask only for unresolved user decisions, and omit unspecified optional settings. Keep
|
|
211
|
+
the returned `batch_id` and `links`.
|
|
212
|
+
6. **Poll until done.** Call `get_remix_batch` for the returned batch (or use
|
|
213
|
+
`list_brand_creatives`) every ~20-30s
|
|
214
214
|
until every creative's `pending` is 0. Most images finish in a few minutes; text-heavy templates
|
|
215
215
|
and `quality: high` take longer. Read each render's `elapsed_seconds` rather than guessing — a
|
|
216
216
|
render that's still `running` is healthy; do NOT re-submit thinking it stalled (that double-bills).
|
|
@@ -219,17 +219,14 @@ for template choice — they've chosen — but still confirm the styling default
|
|
|
219
219
|
|
|
220
220
|
## Workflow — edit an existing ad
|
|
221
221
|
|
|
222
|
-
User wants to tweak a creative they already made → `regenerate_creative
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
`prompt` = the change.
|
|
227
|
-
- "run exactly this prompt on the product" → `mode: "exact"`, `source_render_id` + `prompt`.
|
|
228
|
-
Then poll with `get_remix_batch` and hand back the links, same as above.
|
|
222
|
+
User wants to tweak a creative they already made → use `regenerate_creative`. Infer whether they
|
|
223
|
+
want another take, a targeted edit, or an exact instructed change from their request. Then inspect
|
|
224
|
+
the live schema, ask only for any required source or instruction that is still missing, submit,
|
|
225
|
+
poll with `get_remix_batch`, and hand back the links.
|
|
229
226
|
|
|
230
227
|
## Brand research
|
|
231
228
|
|
|
232
|
-
Prefer the backend's result: `get_brand_kit
|
|
229
|
+
Prefer the backend's result: call `get_brand_kit` for the selected brand. If `researchStatus` is
|
|
233
230
|
`complete`, REUSE it — never re-research.
|
|
234
231
|
|
|
235
232
|
**The split — backend owns visuals, you own the qualitative depth:**
|
|
@@ -246,9 +243,10 @@ Prefer the backend's result: `get_brand_kit { brand_id }`. If `researchStatus` i
|
|
|
246
243
|
|
|
247
244
|
**CLI brand-research flow:**
|
|
248
245
|
|
|
249
|
-
1.
|
|
246
|
+
1. Inspect and call `create_ad_brand` with the known brand identity and website, then keep its id
|
|
247
|
+
and slug. The brand comes back with
|
|
250
248
|
`research_status: "pending"` (light pass in flight).
|
|
251
|
-
2. **Wait for the backend light pass:** poll `get_brand_kit
|
|
249
|
+
2. **Wait for the backend light pass:** poll `get_brand_kit` for that brand until `researchStatus`
|
|
252
250
|
is `complete` (usually <60s). Now the kit has authoritative logo/colors/fonts + a baseline.
|
|
253
251
|
At this point generation is already unblocked — but do the deep pass to make it good.
|
|
254
252
|
3. **Deep research locally:** `gooseworks fetch brand-research` and follow its phases. **Ground
|
|
@@ -262,10 +260,10 @@ Prefer the backend's result: `get_brand_kit { brand_id }`. If `researchStatus` i
|
|
|
262
260
|
(`brandType` ∈ product | saas | service | agency | restaurant | fashion | beauty | fitness |
|
|
263
261
|
finance | education | health). Only URLs already in our storage for product images.
|
|
264
262
|
- **Do NOT set logo / colors / fonts here** — the backend light pass already owns those.
|
|
265
|
-
5. **Persist it:** `finalize_brand_research
|
|
263
|
+
5. **Persist it:** call `finalize_brand_research` for the brand. It merges `kit-patch.json` into the kit
|
|
266
264
|
NON-CLOBBERINGLY (it will NOT overwrite the backend's visuals or any user edit), then re-confirms
|
|
267
265
|
`research_status: complete`.
|
|
268
|
-
6. **Verify:** `get_brand_kit
|
|
266
|
+
6. **Verify:** call `get_brand_kit` again and confirm the qualitative fields you wrote are present
|
|
269
267
|
before generating.
|
|
270
268
|
|
|
271
269
|
**If the brand has NO website**, the backend light pass can't run (nothing to fetch) — do the whole
|
|
@@ -305,20 +303,26 @@ run through the `gooseworks` CLI (`gooseworks fetch` / `gooseworks call`), like
|
|
|
305
303
|
each creative's `app_url`), copied verbatim. Never end on just "done" or a file path.
|
|
306
304
|
- **Quote cost before generating** when it's non-trivial (use `estimate_remix_batch`), and
|
|
307
305
|
relay `insufficient_credits` plainly if the submit is rejected — don't retry blindly.
|
|
308
|
-
- **
|
|
309
|
-
|
|
310
|
-
`surprise_me_templates`;
|
|
306
|
+
- **Use approved source paths.** If the user didn't name a source, run the ask flow (own ads,
|
|
307
|
+
Community, upload, Surprise me, or browse in the app). "Surprise me" goes through
|
|
308
|
+
`surprise_me_templates`; browsing uses `/create?brand=<slug>&cli=true`. Never use the retired
|
|
309
|
+
curated third-party catalog.
|
|
311
310
|
Generate when they paste the app's copyable remix prompt back (or submit the surprise picks
|
|
312
311
|
directly if they'd rather not review).
|
|
313
|
-
- **
|
|
312
|
+
- **Treat competitor ads as inspiration** — never attest rights, imply ownership, or promise to
|
|
313
|
+
copy a competitor's distinctive expression.
|
|
314
314
|
- **Reconcile brand facts into the kit** — when the user states or changes something brand-level
|
|
315
315
|
mid-task, check it against `get_brand_kit` and, with their ok, persist it via `update_brand_kit`
|
|
316
316
|
/ `upsert_brand_product` / `add_brand_product_image` so it sticks for future ads. Ask first;
|
|
317
317
|
never silently mutate the kit.
|
|
318
|
-
- **Record feedback** — when the user reacts to a generated image,
|
|
319
|
-
`set_creative_feedback
|
|
320
|
-
- **Plan mode is opt-in** — only
|
|
321
|
-
|
|
318
|
+
- **Record feedback** — when the user reacts to a generated image, inspect and call
|
|
319
|
+
`set_creative_feedback` so the quality loop learns.
|
|
320
|
+
- **Plan mode is opt-in** — only use the live approval option, then `list_ad_approvals` and
|
|
321
|
+
`approve_ad_plan`, when the user wants to review before spending credits; otherwise generate
|
|
322
322
|
immediately.
|
|
323
323
|
- **Don't busy-loop** — poll `get_remix_batch` on a sensible interval (~20-30s); a `queued`
|
|
324
324
|
batch is waiting on research and will start on its own.
|
|
325
|
+
- **Report problems so we can fix them** — when a batch fails/is rejected and you can't resolve it,
|
|
326
|
+
a required brand input/asset is missing, or a recipe/instruction is ambiguous or contradictory,
|
|
327
|
+
call the **`log_cli_event`** MCP tool (`event_type`: `error`/`blocker`/`missing_input`/`confusion`,
|
|
328
|
+
with the real error + step in `details`) so the team gets visibility. Still tell the user too.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: goose-product-photos
|
|
3
|
+
slug: goose-product-photos
|
|
4
|
+
description: >
|
|
5
|
+
GooseWorks Product Photos — turn a brand's product images into publish-ready photography
|
|
6
|
+
(clean studio shots, lifestyle scenes, on-model looks) while keeping the product faithful
|
|
7
|
+
(silhouette, materials, logo, colorway). You pick a brand + product and submit; the GooseWorks
|
|
8
|
+
backend runs the SAME server-side pipeline the Product Photos studio uses (compose → generate →
|
|
9
|
+
judge → auto-retry) and bills credits. Use when the user says "make product photos", "shoot my
|
|
10
|
+
product", "studio/lifestyle/on-model photo of <product>", "generate product photography", or
|
|
11
|
+
references a product to photograph. Unlike goose-ads (ad creative) this produces clean PRODUCT
|
|
12
|
+
photos that can then feed the ad workflow.
|
|
13
|
+
category: ads
|
|
14
|
+
version: 0.1.0
|
|
15
|
+
author: GooseWorks
|
|
16
|
+
tags: [gooseworks, ads, product-photos, photoshoot, product, ecommerce, studio, lifestyle, on-model]
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
# GooseWorks Product Photos — branded product photography
|
|
20
|
+
|
|
21
|
+
The GooseWorks Product Photos skill. You **pick a brand + product and submit one generation**;
|
|
22
|
+
the **backend** runs the whole pipeline (compose the shot prompt → generate on `gpt_image_2` →
|
|
23
|
+
judge for product fidelity → auto-retry a few times for free) and stores the results. You do NOT
|
|
24
|
+
generate images, call a model, or manage files — this is the exact same workflow the Product
|
|
25
|
+
Photos studio uses, so the skill and the app can never drift. The point is to **enrich a brand's
|
|
26
|
+
usable product imagery** — approved photos join the brand kit and can then feed the ad workflow
|
|
27
|
+
(`goose-ads`).
|
|
28
|
+
|
|
29
|
+
## Prerequisite — the GooseWorks MCP server is REQUIRED
|
|
30
|
+
|
|
31
|
+
Everything goes through the `mcp__gooseworks__*` tools. If they are not available, **stop and
|
|
32
|
+
tell the user to run `gooseworks install --claude --mcp`** (and restart Claude Code). There is no
|
|
33
|
+
HTTP/file fallback.
|
|
34
|
+
|
|
35
|
+
## Identity & credits
|
|
36
|
+
|
|
37
|
+
- One agent-scoped token authenticates the tools; they resolve your org automatically. Never
|
|
38
|
+
print the token. (You may pass an optional `target` to operate on a specific agent/org, exactly
|
|
39
|
+
as the other GooseWorks tools; omit it to use your pinned scope.)
|
|
40
|
+
- **Credits are handled by the backend.** `generate_product_photos` reserves the estimated cost up
|
|
41
|
+
front and bills only the photos that pass the judge — **automatic retries are free**, and a photo
|
|
42
|
+
the judge can't get right (`flagged`) is shown but **never billed**. Call
|
|
43
|
+
`estimate_product_photos` first to quote the cost; `get_ad_credits` shows the balance.
|
|
44
|
+
|
|
45
|
+
## The tools
|
|
46
|
+
|
|
47
|
+
**Pick the brand + product**
|
|
48
|
+
- `list_ad_brands` — the user's ad brands (get a `brand_id`; also carries `slug`).
|
|
49
|
+
- `list_brand_products { brand_id, search?, page?, page_size? }` — the brand's imported products.
|
|
50
|
+
Pick a `product_id` to shoot. `search` matches name / type / variant / SKU.
|
|
51
|
+
- `import_product { brand_id, kind, url, product_name? }` — import a product if it isn't in the
|
|
52
|
+
catalog yet. `kind` is `product_url` (a single product page), `shopify_store` (a store URL →
|
|
53
|
+
imports the catalog), or `image_url` (a direct image; requires `product_name`). Returns an import
|
|
54
|
+
row with an `id`; if its `status` isn't `complete`, poll `get_product_import` until it is, then
|
|
55
|
+
`list_brand_products` to find the new product. (File uploads aren't available over MCP — use a URL.)
|
|
56
|
+
- `get_product_import { import_id }` — poll an import until `status` is `complete` or `failed`.
|
|
57
|
+
|
|
58
|
+
**Generate**
|
|
59
|
+
- `estimate_product_photos { count, quality? }` — cost preview (per-photo + total credits). `count`
|
|
60
|
+
is 1, 2, 4, or 8; `quality` is `low` | `medium` | `high` (default `medium`). Reserves nothing.
|
|
61
|
+
- `generate_product_photos { brand_id, product_id, variant_id?, category, controls?, prompt?,
|
|
62
|
+
count?, quality?, reference_image_urls?, attestation_accepted? }` — **the one call that makes
|
|
63
|
+
photos.** `category` is `apparel` | `beauty` | `cpg` (seeds sensible scene/framing defaults).
|
|
64
|
+
Omit `controls` to use the category preset; pass `prompt` as free-text steering **added on top of**
|
|
65
|
+
the settings (it doesn't replace them). Returns a generation with an `id` **immediately** — poll
|
|
66
|
+
`get_product_photo_generation` until done, then read each `outputs[].final_image_url`.
|
|
67
|
+
**If you request a human model** (`controls.model.presence` is not `none`) you MUST pass
|
|
68
|
+
`attestation_accepted: true` to confirm the user has the rights for model imagery.
|
|
69
|
+
- `get_product_photo_generation { generation_id }` — poll until `status` is `complete`,
|
|
70
|
+
`partial_failure`, or `failed`. Each `outputs[]` entry has its own `status` and, once ready, a
|
|
71
|
+
`final_image_url`. A `flagged` output is the best attempt but wasn't billed.
|
|
72
|
+
|
|
73
|
+
**Use the results**
|
|
74
|
+
- `list_product_photos { brand_id, archived? }` — the brand's generated photos (`archived: false`
|
|
75
|
+
= active, `true` = archived).
|
|
76
|
+
- `approve_product_photo { output_id }` — approve a photo: links it to the product and makes it
|
|
77
|
+
available in the **brand kit**, so `goose-ads` can use it. **Photos are not used anywhere until
|
|
78
|
+
approved.**
|
|
79
|
+
- `archive_product_photo { output_id, reason? }` — archive a photo; archived photos are **excluded**
|
|
80
|
+
from ad generation.
|
|
81
|
+
|
|
82
|
+
## Workflow — shoot a product
|
|
83
|
+
|
|
84
|
+
1. **Resolve the brand + product.** `list_ad_brands` → `brand_id`. `list_brand_products` → pick a
|
|
85
|
+
`product_id`. If the product isn't there, `import_product` (poll `get_product_import`).
|
|
86
|
+
2. **Quote the cost.** `estimate_product_photos { count, quality }` → tell the user credits.
|
|
87
|
+
3. **Generate.** `generate_product_photos { brand_id, product_id, category, count, quality, prompt? }`.
|
|
88
|
+
Returns a generation `id` right away.
|
|
89
|
+
4. **Poll.** `get_product_photo_generation { generation_id }` until terminal; hand back each
|
|
90
|
+
`final_image_url`.
|
|
91
|
+
5. **Approve the keepers.** Show the results and let the user pick; `approve_product_photo` the ones
|
|
92
|
+
they'd publish (that's what puts them in the brand kit for ads), `archive_product_photo` the rest.
|
|
93
|
+
|
|
94
|
+
## Rules
|
|
95
|
+
|
|
96
|
+
- **Never invent product facts.** The backend grounds the shot on the product's real images; don't
|
|
97
|
+
describe a product you can't see.
|
|
98
|
+
- **Ask before spending.** Quote the estimate and confirm `count` / `quality` before
|
|
99
|
+
`generate_product_photos` — it reserves credits.
|
|
100
|
+
- **Poll, don't re-submit.** A generation that's still `running` is not stuck; re-submitting
|
|
101
|
+
double-bills. Only a `failed` generation should be retried.
|
|
102
|
+
- **Model imagery needs consent.** Only set a human model when the user asks, and pass
|
|
103
|
+
`attestation_accepted: true`.
|
|
104
|
+
- **Approval is the hand-off to ads.** Remind the user that only **approved** photos reach the brand
|
|
105
|
+
kit / ad workflow; archived ones never do.
|
|
@@ -45,6 +45,26 @@ says to shell out, use the MCP equivalent:
|
|
|
45
45
|
- `gooseworks credits` → the **`get_ad_credits`** MCP tool.
|
|
46
46
|
- `gooseworks doctor` → do the manual toolchain check in the preflight below.
|
|
47
47
|
|
|
48
|
+
## Report problems so we can fix them (telemetry — do this, don't skip it)
|
|
49
|
+
|
|
50
|
+
If anything blocks or degrades this run — a media/proxy call fails or errors, a required input or
|
|
51
|
+
asset is missing, a recipe instruction is ambiguous or contradictory, the render toolchain won't set
|
|
52
|
+
up, or you hit a bug you can't work around — **report it** so the team gets visibility and can fix
|
|
53
|
+
the skill. It's fire-and-forget, never counts against you, and never blocks your work.
|
|
54
|
+
|
|
55
|
+
- **First, set a stable run id** so every event (yours + the auto-logged media calls) groups together:
|
|
56
|
+
`export GW_RUN_ID="vid-<project_or_batch_id>"` (and `export GW_SKILL="<recipe-slug>"`) in the
|
|
57
|
+
shell you render from. The media proxies read `GW_RUN_ID` automatically.
|
|
58
|
+
- **CLI present →** `gooseworks log "<what happened>" --event-type <type> --level error --details '{"error":"...","step":"...","model":"..."}'`
|
|
59
|
+
- **No CLI (cowork / headless) →** the **`log_cli_event`** MCP tool with the same fields (pass `run_id`).
|
|
60
|
+
- `--event-type`: `api_failure` (a proxy/model call failed) · `missing_input` · `blocker` ·
|
|
61
|
+
`confusion` (unclear/contradictory instruction) · `error` (a bug) · `step`/`info` (progress notes).
|
|
62
|
+
- Put the **real error text + the step you were on** in `--details`. Paid FAL/ElevenLabs calls
|
|
63
|
+
ALREADY auto-log their own failures, so focus your manual logs on what the proxy can't see:
|
|
64
|
+
missing inputs, confusing/contradictory recipe instructions, toolchain/setup failures, and bugs.
|
|
65
|
+
- Logging is FOR US — it does not replace telling the user. When a problem blocks the run, still
|
|
66
|
+
explain it to the user (and ask if you need a decision); just also `log` it so we can fix the skill.
|
|
67
|
+
|
|
48
68
|
## Prerequisite — MCP + a render toolchain (Phase 0 preflight)
|
|
49
69
|
|
|
50
70
|
- The `mcp__gooseworks__*` tools are REQUIRED. If they're unavailable, stop and tell the user
|
|
@@ -414,5 +434,8 @@ path. (`fal-storage-proxy` may 404 depending on the install; don't block on it
|
|
|
414
434
|
- **Verify a real, non-empty MP4** (watch it) before marking the render complete.
|
|
415
435
|
- **Reuse the brand** when its research is complete; never re-research.
|
|
416
436
|
- On a hard error (auth/quota/model/timeout) set the render `failed` with a short
|
|
417
|
-
`error_message` and stop — don't ship the source unchanged.
|
|
437
|
+
`error_message` and stop — don't ship the source unchanged. **Also `log` it** (`gooseworks log`
|
|
438
|
+
/ `log_cli_event`, `--event-type api_failure|error`) so we can see + fix it (see "Report problems").
|
|
439
|
+
- **Report blockers/bugs/confusing instructions via telemetry** (`gooseworks log` or the
|
|
440
|
+
`log_cli_event` MCP tool) — not just to the user. Set `GW_RUN_ID` once so events group.
|
|
418
441
|
- Always end a successful run with `app_url` + `brand_url`, verbatim.
|