gooseworks 0.3.16 → 0.4.0
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 +9 -9
- package/dist/agents/claude.js +1 -1
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/codex.js +1 -1
- package/dist/agents/codex.js.map +1 -1
- package/dist/agents/skill-links.d.ts +7 -2
- package/dist/agents/skill-links.d.ts.map +1 -1
- package/dist/agents/skill-links.js +10 -5
- package/dist/agents/skill-links.js.map +1 -1
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +10 -6
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +3 -23
- package/dist/commands/login.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -2
- package/dist/config.js.map +1 -1
- package/dist/skills/installer.d.ts +9 -0
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +20 -6
- package/dist/skills/installer.js.map +1 -1
- package/dist/skills/master-skill.d.ts +24 -22
- package/dist/skills/master-skill.d.ts.map +1 -1
- package/dist/skills/master-skill.js +251 -66
- package/dist/skills/master-skill.js.map +1 -1
- package/dist/skills/names.d.ts +53 -1
- package/dist/skills/names.d.ts.map +1 -1
- package/dist/skills/names.js +107 -7
- package/dist/skills/names.js.map +1 -1
- package/dist/skills/routes.d.ts +68 -0
- package/dist/skills/routes.d.ts.map +1 -0
- package/dist/skills/routes.js +124 -0
- package/dist/skills/routes.js.map +1 -0
- package/package.json +1 -1
- package/skills/goose-ads/SKILL.md +23 -3
- package/skills/goose-product-photos/SKILL.md +27 -3
- package/skills/gooseworks/SKILL.md +50 -49
- package/skills/routes.json +157 -0
|
@@ -1,17 +1,56 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getEntrySkills = getEntrySkills;
|
|
4
|
+
exports.getEntrySkillNames = getEntrySkillNames;
|
|
4
5
|
exports.getMasterSkillContent = getMasterSkillContent;
|
|
5
6
|
exports.getGooseAdsSkillContent = getGooseAdsSkillContent;
|
|
6
7
|
exports.getGooseVideoSkillContent = getGooseVideoSkillContent;
|
|
7
|
-
|
|
8
|
+
exports.getGooseProductPhotosSkillContent = getGooseProductPhotosSkillContent;
|
|
9
|
+
/**
|
|
10
|
+
* The CLI installs two vendored ENTRY skills into ~/.agents/skills/:
|
|
11
|
+
* - `gooseworks` — the PARENT router (getMasterSkillContent): GTM/data toolkit
|
|
12
|
+
* PLUS a domain router that hands ads/graphics/video work to the dedicated
|
|
13
|
+
* `goose-*` skills below.
|
|
14
|
+
* - `goose-ads` — the ads entry/contract (getGooseAdsSkillContent): ad creative
|
|
15
|
+
* (remix, brand research) AND ad analytics/intelligence. Formerly `ads-remix`.
|
|
16
|
+
* Each is a separate Claude Code skill; Claude auto-loads whichever matches the
|
|
17
|
+
* task by its description. They are domain-scoped on purpose — do NOT merge them.
|
|
18
|
+
*
|
|
19
|
+
* Sibling domain skills NOT vendored here (fetched live from goose-skills):
|
|
20
|
+
* - `goose-graphics` — charts/slides/infographics/branded visuals. Installed via
|
|
21
|
+
* `gooseworks install --with goose-graphics` or fetched on demand.
|
|
22
|
+
* - `goose-video` — video ad remix: fetches the per-format recipe by slug,
|
|
23
|
+
* renders LOCALLY (Playwright + ffmpeg + media proxies), mirrors a script for
|
|
24
|
+
* in-app review, saves the MP4 back over MCP (getGooseVideoSkillContent).
|
|
25
|
+
*
|
|
26
|
+
* Recipe skills (remix-graphic-ad-from-reference, brand-research, meta-ads-analyzer,
|
|
27
|
+
* …) are NOT vendored here — they live in goose-skills and are fetched live on
|
|
28
|
+
* demand via `gooseworks fetch <slug>`, so they're always current.
|
|
29
|
+
*/
|
|
30
|
+
const routes_1 = require("./routes");
|
|
31
|
+
/**
|
|
32
|
+
* THE registry of entry skills (GOOSE-3190) — one list, four consumers:
|
|
33
|
+
* - `gooseworks install` / `update` / login-refresh write exactly these dirs,
|
|
34
|
+
* - `npm run generate:skills` regenerates exactly these `skills/<name>/SKILL.md`,
|
|
35
|
+
* - `skills/names.ts` derives which dirs the CLI is allowed to delete,
|
|
36
|
+
* - the backend raw-fetches these paths for hosted connectors.
|
|
37
|
+
*
|
|
38
|
+
* `goose-product-photos` used to be a hand-maintained `skills/…/SKILL.md` that
|
|
39
|
+
* was on disk and served by the backend but absent here — so it was never
|
|
40
|
+
* regenerated and never refreshed on install. Adding it closes that drift.
|
|
41
|
+
*/
|
|
8
42
|
function getEntrySkills() {
|
|
9
43
|
return [
|
|
10
44
|
{ name: 'gooseworks', content: getMasterSkillContent() },
|
|
11
45
|
{ name: 'goose-ads', content: getGooseAdsSkillContent() },
|
|
12
46
|
{ name: 'goose-video', content: getGooseVideoSkillContent() },
|
|
47
|
+
{ name: 'goose-product-photos', content: getGooseProductPhotosSkillContent() },
|
|
13
48
|
];
|
|
14
49
|
}
|
|
50
|
+
/** Just the directory names, for callers that don't need the bodies. */
|
|
51
|
+
function getEntrySkillNames() {
|
|
52
|
+
return getEntrySkills().map((s) => s.name);
|
|
53
|
+
}
|
|
15
54
|
/**
|
|
16
55
|
* Returns the GTM master SKILL.md content (the `gooseworks` entry skill).
|
|
17
56
|
* It teaches the coding agent how to discover and use GooseWorks skills on
|
|
@@ -44,19 +83,37 @@ This skill is also the **parent router** for the GooseWorks family. Data/GTM wor
|
|
|
44
83
|
|
|
45
84
|
## Route to the right skill FIRST
|
|
46
85
|
|
|
47
|
-
|
|
86
|
+
First apply the **Common company onboarding** gate below. Preserve the user's original request while onboarding, then continue with it as soon as onboarding is complete. Then load the brand context (**"Load the brand context FIRST"**, immediately below). After that, check whether the request belongs to a specialized domain. If so, **switch to that skill** instead of the data flow below:
|
|
48
87
|
|
|
49
88
|
| If the user wants… | Route to | How |
|
|
50
89
|
| --- | --- | --- |
|
|
51
|
-
|
|
52
|
-
| Charts, infographics, slides, social graphics, branded visual designs from a style/format | **\`goose-graphics\`** | If installed locally, use it. Otherwise \`gooseworks fetch goose-graphics\` (or \`gooseworks install --claude --with goose-graphics\`). |
|
|
53
|
-
| Make a **video** ad — remix a video ad template (e.g. iMessage chat-reveal), or "make the video for project <id>" | **\`goose-video\`** | Installed locally as an entry skill. Just use it. If unavailable, run \`gooseworks install --claude\`. |
|
|
54
|
-
| Make **product photos** — studio, lifestyle, marketplace, social, or on-model product photography | **\`goose-product-photos\`** | Installed locally as an entry skill. Just use it. If unavailable, run \`gooseworks install --claude\`. |
|
|
55
|
-
| Animate an approved static ad or product image | **\`animate-image\`** | Fetch with \`gooseworks fetch animate-image\` and follow its GooseWorks MCP workflow. |
|
|
90
|
+
${(0, routes_1.renderDomainRouteTable)()}
|
|
56
91
|
| Anything else — scraping, research, lead gen, enrichment, any data lookup | (stay here) | Follow "How to Use" below. |
|
|
57
92
|
|
|
58
93
|
Examples — all of these route to \`goose-ads\`, not the data flow: "remix this ad with project id 123", "make an ad for my product", "research my brand", "why is my Meta campaign underperforming", "which creatives should I cut".
|
|
59
94
|
|
|
95
|
+
## Load the brand context FIRST (mandatory — before you route, and before you ask anything)
|
|
96
|
+
|
|
97
|
+
**Call \`brand_get_context\` before the first substantive step of ANY task**, and before you route to a specialist skill. It is a cheap, read-only call that returns the brand's canonical facts:
|
|
98
|
+
|
|
99
|
+
| It returns | Use it for |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| **voice** — tone, style, banned phrasing | Any copy, script, caption, hook, or headline. Don't ask "what tone?" |
|
|
102
|
+
| **products** — names, descriptions, pricing, links, imagery | Picking the product to feature. Don't ask "which product?" — offer the list. |
|
|
103
|
+
| **audience** — segments, demographics, jobs-to-be-done | Targeting, angles, creator fit. Don't ask "who is this for?" |
|
|
104
|
+
| **positioning** — category, value props, proof points, tagline | Angles, offers, competitive framing. Don't ask "what makes you different?" |
|
|
105
|
+
| **research status** — whether the brand's research pass has completed | Whether the facts are trustworthy yet, or still being filled in. |
|
|
106
|
+
|
|
107
|
+
Then:
|
|
108
|
+
|
|
109
|
+
1. **Pass what it returned INTO the routed skill.** When you hand off to \`goose-ads\`, \`goose-video\`, \`goose-product-photos\`, \`goose-graphics\`, or a fetched Brand Growth recipe, carry the voice / products / audience / positioning with you. Do **not** make the routed skill re-derive them, and do **not** re-run brand research when the context is already there.
|
|
110
|
+
2. **Never re-ask the user for something the brand context already answers.** If a routed skill's own prose asks a question the context answers, the context wins — answer it yourself and move on. Ask only for what is genuinely missing or ambiguous.
|
|
111
|
+
3. **If research status is not complete**, say so in one line, use what you have, and continue. Only run brand research when the context comes back empty or the user asks for it.
|
|
112
|
+
4. **If \`brand_get_context\` is unavailable** (no MCP connection), fall back to \`get_brand_kit\` for the selected brand and treat its fields the same way. If neither is available, tell the user the GooseWorks MCP connection is needed rather than guessing brand facts.
|
|
113
|
+
5. **Treat it as read-only.** Writing brand facts back is the reconciliation flow in \`goose-ads\` (ask first, then \`update_brand_kit\`) — not something this router does.
|
|
114
|
+
|
|
115
|
+
Never invent a brand fact. If it isn't in the brand context and the user hasn't said it, ask.
|
|
116
|
+
|
|
60
117
|
## Setup
|
|
61
118
|
|
|
62
119
|
All commands below auto-load credentials from \`~/.gooseworks/credentials.json\`. If a command exits with "Not logged in", tell the user to run: \`npx gooseworks login\`. To log out: \`npx gooseworks logout\`.
|
|
@@ -93,57 +150,32 @@ gooseworks credits
|
|
|
93
150
|
|
|
94
151
|
## Common company onboarding
|
|
95
152
|
|
|
96
|
-
Onboarding
|
|
97
|
-
|
|
98
|
-
The CLI and GooseWorks Ads share one brand-scoped questionnaire through these MCP tools:
|
|
99
|
-
|
|
100
|
-
- \`list_ad_brands\` and \`create_ad_brand\` — select or create the company/brand.
|
|
101
|
-
- \`get_brand_onboarding { brand_id }\` — load completed answers and \`missing_fields\` before asking anything.
|
|
102
|
-
- \`update_brand_onboarding { brand_id, ...answers }\` — save each group of answers and the final first-task choice.
|
|
103
|
-
|
|
104
|
-
If these tools are unavailable, tell the user that onboarding needs the GooseWorks MCP connection. Do not send them to another UI and do not fall back to a separate context record.
|
|
105
|
-
|
|
106
|
-
### Resume rules
|
|
107
|
-
|
|
108
|
-
1. Run \`list_ad_brands\`. If there are multiple brands, ask which one to use.
|
|
109
|
-
2. If there is no brand, ask for the company or brand website, research it, and use \`create_ad_brand { name, website_url }\`. If the domain matches an existing brand, reuse it.
|
|
110
|
-
3. Call \`get_brand_onboarding\` and ask only the returned missing questions.
|
|
111
|
-
4. Save after each small group so an interrupted interview can resume.
|
|
112
|
-
5. If the record is complete, confirm the brand and continue; do not repeat the interview.
|
|
113
|
-
|
|
114
|
-
### Shared questions and answer values
|
|
153
|
+
Onboarding happens inside the current agent and is the first-run gate for every GooseWorks task. It uses the exact same saved state and step order as the web onboarding. The user does not need to type **\`/gooseworks onboard me\`**; that explicit command only starts or resumes the same flow.
|
|
115
154
|
|
|
116
|
-
|
|
155
|
+
Keep the user's original task pending. Call **\`brand_onboarding { action: "status" }\`** before routing or executing it, then:
|
|
117
156
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
4. **Who makes your ad creatives right now?** and **Who manages your ads right now?** Use the shared values returned in the tool schema. Skip both when ad spend is \`zero\` and no advertising goal was selected.
|
|
122
|
-
5. **Which platforms or channels do you use or want help with?** Multi-select: \`meta\` · \`tiktok\` · \`google\` · \`chatgpt\` · \`x\` · \`linkedin\` · \`reddit\` · \`other\`.
|
|
123
|
-
6. **Where did you find GooseWorks?** Use the shared discovery-source values returned in the tool schema.
|
|
157
|
+
- follow only the returned \`next_step\`;
|
|
158
|
+
- save each answer immediately with \`brand_onboarding\` so web, Claude, Codex, ChatGPT, and Cowork can resume one another;
|
|
159
|
+
- continue the original request immediately when \`onboarding_completed\` is true.
|
|
124
160
|
|
|
125
|
-
|
|
161
|
+
If \`brand_onboarding\` is unavailable, explain that the GooseWorks MCP connection must be enabled. Do not write a parallel local profile and do not run the retired role / discovery-source / ad-owner questionnaire.
|
|
126
162
|
|
|
127
|
-
|
|
163
|
+
When onboarding returns a review link, show that single link and ask the user to review the creatives and reply \`done\`. When they reply \`done\`, do not restart onboarding: continue the task they originally asked for. If there was no earlier task, ask: **“Let’s start your next campaign. What are you promoting, and what result do you want?”** Use the same preserved-task-or-campaign handoff if onboarding completes while the creatives are still being prepared or could not be generated.
|
|
128
164
|
|
|
129
|
-
|
|
165
|
+
### Shared flow
|
|
130
166
|
|
|
131
|
-
|
|
132
|
-
2. Reuse existing Brand Kit/Core data. For an ecommerce store, import the relevant catalog with \`import_product\` and poll \`get_product_import\` rather than submitting duplicates.
|
|
133
|
-
3. When ads are relevant, offer to import existing creative. This is optional.
|
|
134
|
-
4. Suggest evidence-backed messaging angles. Approval is optional and never blocks completion.
|
|
135
|
-
5. Show the researched profile for confirmation: products/services, audience, competitors, imported ads, and suggested angles. Clearly label uncertainty.
|
|
167
|
+
Use the host's native question controls. Ask one short group at a time and rely on the live tool schema for accepted values.
|
|
136
168
|
|
|
137
|
-
|
|
169
|
+
1. **Start** — If status returns \`start\`, ask for the company website or Apple App Store URL. Also offer the optional hero product URL and “Where do you do your work?” choices: Slack, WhatsApp, iMessage, Claude Code, Claude, Codex, and ChatGPT. Call \`action: "start"\`; server-side research begins immediately. If status returns \`select_brand\`, ask which company/client to use. Otherwise reuse the only brand automatically.
|
|
170
|
+
2. **Your coworker** — Ask what they want to name their Growth Coworker. A text-only client may keep the default avatar; do not block on an image. Save with \`action: "save_coworker"\`.
|
|
171
|
+
3. **Your company** — Use the returned \`company_draft\` as the starting point and ask the user to verify or edit: what they sell (\`marketCategory\`), where people buy (\`appPlatforms\`), primary customer, customer problem, promised outcome, and optional differentiator. Save with \`action: "save_company"\`.
|
|
172
|
+
4. **Your taste** — In a terminal or CLI host, use the returned \`taste_url\`: open it when the host supports opening links and always show one clickable **Choose your taste in GooseWorks** link. Ask the user to heart or skip ads on that page, click **Continue** or **Skip this**, return to the agent, and reply \`done\`. Do not print, enumerate, or summarize \`taste_deck\` in the terminal. After \`done\`, call \`brand_onboarding { action: "status" }\` again and follow the refreshed \`next_step\`. In a chat host that renders images, show only the one image attached by the tool and save each Love/Skip decision with \`action: "save_taste"\`; send \`complete: true\` after three hearts or an explicit skip.
|
|
173
|
+
5. **First campaign** — Ask **“What’s happening right now?”**: launch \`launch\`, promotion \`promo\`, seasonal moment \`seasonal\`, or nothing special \`nothing\`, plus an optional note. Call \`action: "propose_campaign"\`, show the returned editable card (name, objective, offer, audience, 2–3 angles, CTA, and product URL), and save edits with \`action: "save_campaign"\`. Send \`accept: true\` only after approval; acceptance can start the complimentary first creatives.
|
|
174
|
+
6. **Where you are** — Ask monthly ad spend (\`none\`, \`under_1k\`, \`1k_5k\`, \`5k_25k\`, \`25k_plus\`), annual revenue (\`under_1m\`, \`1m_10m\`, \`10m_100m\`, \`100m_plus\`), the 90-day goal, current channels (an empty list is a valid “nothing yet”), and at least one channel they are willing to use. Channel values: \`paid_social\`, \`search_ads\`, \`content\`, \`creators\`, \`seo\`, \`communities\`, \`referrals\`, \`partnerships\`, \`outbound\`, \`app_stores\`, \`other\`. Save with \`action: "save_progress"\`.
|
|
175
|
+
7. **Review** — Show the returned founder, researched, and inferred facts with their provenance. The user may correct positioning, audience, voice, value propositions, proof points, or competitors through \`action: "review_research"\`. Complete the review even when research is still running, failed, or sparse; never trap the user waiting for it.
|
|
176
|
+
8. **Channels** — If \`channel_connected\` is already true, this is complete automatically. Otherwise ask whether they want to connect Slack, WhatsApp, or iMessage later, or skip for now. An explicit skip is valid; call \`action: "complete_channels"\`.
|
|
138
177
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
- Connect my tools and data — \`connect_tools\`
|
|
142
|
-
- Research customers, competitors, creators, or trends — \`research\`
|
|
143
|
-
- Analyze ads, content, landing pages, or performance — \`analyze\`
|
|
144
|
-
- Create ads, product images, or social content — \`create\`
|
|
145
|
-
|
|
146
|
-
Save the choice as \`first_task\`, then start that job. If the user already stated a concrete job, save the matching value and start without showing the menu.
|
|
178
|
+
Do not ask for role, discovery source, who makes creatives, who manages ads, or a separate “what do you want to do first?” menu. Those belonged to the retired CLI questionnaire. The task the user already asked for is their first task.
|
|
147
179
|
|
|
148
180
|
## Brand Growth discovery
|
|
149
181
|
|
|
@@ -151,19 +183,9 @@ Brand Growth is a collection inside the normal skill catalog, not a command or i
|
|
|
151
183
|
|
|
152
184
|
| Job | Skill |
|
|
153
185
|
| --- | --- |
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
| Competitor social content | \`competitor-social-research\` |
|
|
158
|
-
| Creator discovery and evaluation | \`influencer-prospecting\` |
|
|
159
|
-
| Trends and outlier posts | \`trend-discovery\`, \`outlier-post-finder\` |
|
|
160
|
-
| Social listening and product demand | \`social-listening-brief\`, \`product-demand-research\` |
|
|
161
|
-
| Meta performance, policy, and landing-page match | \`meta-ads-analyzer\`, \`meta-ad-policy-checker\`, \`ad-to-landing-page-auditor\` |
|
|
162
|
-
| Static ads | \`goose-ads\` / \`remix-graphic-ad-from-reference\` |
|
|
163
|
-
| Product photos | \`goose-product-photos\` |
|
|
164
|
-
| Graphics and animation | \`goose-graphics\`, \`animate-image\` |
|
|
165
|
-
|
|
166
|
-
Fetch the named public skill before following it. Provider helpers such as \`scrapecreators-api\` and \`transcript-intelligence\` are dependencies, not user-facing results.
|
|
186
|
+
${(0, routes_1.renderBrandGrowthTable)()}
|
|
187
|
+
|
|
188
|
+
Fetch the named public skill before following it. You already called \`brand_get_context\` — hand the brand's voice, products, audience, and positioning to the fetched skill instead of letting it re-derive or re-ask them. Provider helpers such as \`scrapecreators-api\` and \`transcript-intelligence\` are dependencies, not user-facing results.
|
|
167
189
|
|
|
168
190
|
For a multi-part request, repeat this routing check before each new job. Fetch and follow the
|
|
169
191
|
closest outcome skill first (for example, \`comment-mining\`, \`creator-profile-teardown\`, or
|
|
@@ -293,6 +315,7 @@ The \`gooseworks\` CLI sends authenticated requests (Bearer \`GOOSEWORKS_API_KEY
|
|
|
293
315
|
|
|
294
316
|
## Rules
|
|
295
317
|
|
|
318
|
+
0. **Call \`brand_get_context\` before anything else**, pass what it returns into whatever skill you route to, and never re-ask the user for a fact it already answers (see "Load the brand context FIRST").
|
|
296
319
|
1. **Consider a GooseWorks skill when it fits the task** — scraping, research, lead gen, enrichment, especially at scale, behind auth, or from a specific source. For a quick lookup your built-in tools are fine; use your judgement and pick the best tool for the user.
|
|
297
320
|
2. **Before paid operations**, tell the user the estimated credit cost
|
|
298
321
|
3. **If a \`gooseworks\` command exits with "Not logged in"**: tell the user to run \`npx gooseworks login\`
|
|
@@ -356,6 +379,24 @@ Everything goes through the \`mcp__gooseworks__*\` tools. If they are not availa
|
|
|
356
379
|
tell the user to run \`gooseworks install --claude --mcp\`** (and restart Claude Code). There is
|
|
357
380
|
no HTTP/file fallback — the REST ad endpoints are session-cookie-only and reject your token.
|
|
358
381
|
|
|
382
|
+
## Start from the brand context — don't re-ask what it already answers
|
|
383
|
+
|
|
384
|
+
If the \`gooseworks\` router handed you brand context, USE IT. If you were invoked directly, call
|
|
385
|
+
\`brand_get_context\` first (falling back to \`get_brand_kit\` for the selected brand). It already
|
|
386
|
+
answers most of what the flows below would otherwise ask the user:
|
|
387
|
+
|
|
388
|
+
- **Which product to feature** → \`products[]\`. Offer the real catalog entries; never guess a
|
|
389
|
+
product name and never ask the user to list their products.
|
|
390
|
+
- **The vibe / tone of the copy** → the brand's **voice**. Use it; don't ask "what tone?".
|
|
391
|
+
- **Who the ad is for** → the brand's **audience**. Don't ask "who's the target?".
|
|
392
|
+
- **The angle, offer framing, and what to claim** → **positioning**, value props, proof points.
|
|
393
|
+
- **Logo, colors, fonts** → owned by the backend research pass. **Never re-derive them.**
|
|
394
|
+
- **Whether the facts are trustworthy yet** → **research status**. If it isn't complete, say so in
|
|
395
|
+
one line and continue; the batch queues and runs when research finishes.
|
|
396
|
+
|
|
397
|
+
Ask only for what the context genuinely doesn't answer: the specific campaign intent (season,
|
|
398
|
+
promo, which of several angles), the source ad, and anything the user must consent to.
|
|
399
|
+
|
|
359
400
|
## Identity & credits
|
|
360
401
|
|
|
361
402
|
- One agent-scoped token authenticates the \`gooseworks\` MCP tools. Never print it. The tools
|
|
@@ -481,9 +522,11 @@ When the user wants to make ads but has NOT named a specific template (id/slug/C
|
|
|
481
522
|
ad/upload), do NOT silently browse the raw catalog and hand-pick for them. Instead run this
|
|
482
523
|
short ask flow — it mirrors the web app and keeps the human in the loop:
|
|
483
524
|
|
|
484
|
-
1. **Ask what kind of ads they want** — the angle/offer/theme/season
|
|
485
|
-
|
|
486
|
-
|
|
525
|
+
1. **Ask what kind of ads they want** — the angle/offer/theme/season. **The brand context already
|
|
526
|
+
gives you the vibe (voice), the audience, and the product catalog — do NOT ask for those.**
|
|
527
|
+
Offer the real \`products[]\` to pick from rather than asking "which product?", and derive the
|
|
528
|
+
tone from the brand's voice. This shapes both the source choice and your steering \`prompt\`.
|
|
529
|
+
Keep it to one quick question about campaign intent.
|
|
487
530
|
2. **Ask how to pick a source: their own ads, Community, upload, or "Surprise me".**
|
|
488
531
|
- **Their own ads** → use \`list_user_ad_templates\` to load the active brand's own sources and
|
|
489
532
|
let them choose from the results.
|
|
@@ -1104,4 +1147,146 @@ path. (\`fal-storage-proxy\` may 404 depending on the install; don't block on it
|
|
|
1104
1147
|
- Always end a successful run with \`app_url\` + \`brand_url\`, verbatim.
|
|
1105
1148
|
`;
|
|
1106
1149
|
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Returns the goose-product-photos entry SKILL.md content.
|
|
1152
|
+
*
|
|
1153
|
+
* GOOSE-3190: this skill already existed on disk (`skills/goose-product-photos/
|
|
1154
|
+
* SKILL.md`, hand-maintained) and was already served by the backend to hosted
|
|
1155
|
+
* connectors — but it was NOT in `getEntrySkills()`, so `npm run generate:skills`
|
|
1156
|
+
* never regenerated it and `install` / `update` / login-refresh never wrote or
|
|
1157
|
+
* refreshed it on a user's machine. Moving the body here makes the registry the
|
|
1158
|
+
* one source: one command emits all four entry skills.
|
|
1159
|
+
*/
|
|
1160
|
+
function getGooseProductPhotosSkillContent() {
|
|
1161
|
+
return `---
|
|
1162
|
+
name: goose-product-photos
|
|
1163
|
+
slug: goose-product-photos
|
|
1164
|
+
description: >
|
|
1165
|
+
GooseWorks Product Photos — turn a brand's product images into publish-ready photography
|
|
1166
|
+
(clean studio shots, lifestyle scenes, on-model looks) while keeping the product faithful
|
|
1167
|
+
(silhouette, materials, logo, colorway). You pick a brand + product and submit; the GooseWorks
|
|
1168
|
+
backend runs the SAME server-side pipeline the Product Photos studio uses (compose → generate →
|
|
1169
|
+
judge → auto-retry) and bills credits. Use when the user says "make product photos", "shoot my
|
|
1170
|
+
product", "studio/lifestyle/on-model photo of <product>", "generate product photography", or
|
|
1171
|
+
references a product to photograph. Unlike goose-ads (ad creative) this produces clean PRODUCT
|
|
1172
|
+
photos that can then feed the ad workflow.
|
|
1173
|
+
category: ads
|
|
1174
|
+
version: 0.2.0
|
|
1175
|
+
author: GooseWorks
|
|
1176
|
+
tags: [gooseworks, ads, product-photos, photoshoot, product, ecommerce, studio, lifestyle, on-model]
|
|
1177
|
+
---
|
|
1178
|
+
|
|
1179
|
+
# GooseWorks Product Photos — branded product photography
|
|
1180
|
+
|
|
1181
|
+
The GooseWorks Product Photos skill. You **pick a brand + product and submit one generation**;
|
|
1182
|
+
the **backend** runs the whole pipeline (compose the shot prompt → generate on \`gpt_image_2\` →
|
|
1183
|
+
judge for product fidelity → auto-retry a few times for free) and stores the results. You do NOT
|
|
1184
|
+
generate images, call a model, or manage files — this is the exact same workflow the Product
|
|
1185
|
+
Photos studio uses, so the skill and the app can never drift. The point is to **enrich a brand's
|
|
1186
|
+
usable product imagery** — approved photos join the brand kit and can then feed the ad workflow
|
|
1187
|
+
(\`goose-ads\`).
|
|
1188
|
+
|
|
1189
|
+
## Prerequisite — the GooseWorks MCP server is REQUIRED
|
|
1190
|
+
|
|
1191
|
+
Everything goes through the \`mcp__gooseworks__*\` tools. If they are not available, **stop and
|
|
1192
|
+
tell the user to run \`gooseworks install --claude --mcp\`** (and restart Claude Code). There is no
|
|
1193
|
+
HTTP/file fallback.
|
|
1194
|
+
|
|
1195
|
+
## Start from the brand context — don't re-ask what it already answers
|
|
1196
|
+
|
|
1197
|
+
If the \`gooseworks\` router handed you brand context, USE IT. If you were invoked directly, call
|
|
1198
|
+
\`brand_get_context\` yourself first. It answers most of the setup questions below, so **do not ask
|
|
1199
|
+
the user for them**:
|
|
1200
|
+
|
|
1201
|
+
- **Which product?** — the context's \`products[]\` are the real catalog entries. Offer them; never
|
|
1202
|
+
invent a product or ask the user to describe one you can already see.
|
|
1203
|
+
- **What does it look like / what is it made of?** — grounded in the product's stored images and
|
|
1204
|
+
description. Never guess a material, colorway, or silhouette.
|
|
1205
|
+
- **What vibe / who is it for?** — the context's voice, positioning, and audience already say. Let
|
|
1206
|
+
them shape the scene and styling instead of asking "what mood do you want?".
|
|
1207
|
+
- **Brand look** — logo, colors, and fonts are owned by the backend research pass. Read them, never
|
|
1208
|
+
re-derive them.
|
|
1209
|
+
|
|
1210
|
+
Ask only for the genuinely open choices: the shot \`category\`, how many photos, quality, and
|
|
1211
|
+
whether a human model is wanted (which needs explicit consent — see the rules).
|
|
1212
|
+
|
|
1213
|
+
## Identity & credits
|
|
1214
|
+
|
|
1215
|
+
- One agent-scoped token authenticates the tools; they resolve your org automatically. Never
|
|
1216
|
+
print the token. (You may pass an optional \`target\` to operate on a specific agent/org, exactly
|
|
1217
|
+
as the other GooseWorks tools; omit it to use your pinned scope.)
|
|
1218
|
+
- **Credits are handled by the backend.** \`generate_product_photos\` reserves the estimated cost up
|
|
1219
|
+
front and bills only the photos that pass the judge — **automatic retries are free**, and a photo
|
|
1220
|
+
the judge can't get right (\`flagged\`) is shown but **never billed**. Call
|
|
1221
|
+
\`estimate_product_photos\` first to quote the cost; \`get_ad_credits\` shows the balance.
|
|
1222
|
+
|
|
1223
|
+
## The tools
|
|
1224
|
+
|
|
1225
|
+
**Pick the brand + product**
|
|
1226
|
+
- \`list_ad_brands\` — the user's ad brands (get a \`brand_id\`; also carries \`slug\`).
|
|
1227
|
+
- \`list_brand_products { brand_id, search?, page?, page_size? }\` — the brand's imported products.
|
|
1228
|
+
Pick a \`product_id\` to shoot. \`search\` matches name / type / variant / SKU.
|
|
1229
|
+
- \`import_product { brand_id, kind, url, product_name? }\` — import a product if it isn't in the
|
|
1230
|
+
catalog yet. \`kind\` is \`product_url\` (a single product page), \`shopify_store\` (a store URL →
|
|
1231
|
+
imports the catalog), or \`image_url\` (a direct image; requires \`product_name\`). Returns an import
|
|
1232
|
+
row with an \`id\`; if its \`status\` isn't \`complete\`, poll \`get_product_import\` until it is, then
|
|
1233
|
+
\`list_brand_products\` to find the new product. (File uploads aren't available over MCP — use a URL.)
|
|
1234
|
+
- \`get_product_import { import_id }\` — poll an import until \`status\` is \`complete\` or \`failed\`.
|
|
1235
|
+
|
|
1236
|
+
**Generate**
|
|
1237
|
+
- \`estimate_product_photos { count, quality? }\` — cost preview (per-photo + total credits). \`count\`
|
|
1238
|
+
is 1, 2, 4, or 8; \`quality\` is \`low\` | \`medium\` | \`high\` (default \`medium\`). Reserves nothing.
|
|
1239
|
+
- \`generate_product_photos { brand_id, product_id, variant_id?, category, controls?, prompt?,
|
|
1240
|
+
count?, quality?, reference_image_urls?, attestation_accepted? }\` — **the one call that makes
|
|
1241
|
+
photos.** \`category\` is \`apparel\` | \`beauty\` | \`cpg\` (seeds sensible scene/framing defaults).
|
|
1242
|
+
Omit \`controls\` to use the category preset; pass \`prompt\` as free-text steering **added on top of**
|
|
1243
|
+
the settings (it doesn't replace them). Returns a generation with an \`id\` **immediately** — poll
|
|
1244
|
+
\`get_product_photo_generation\` until done, then read each \`outputs[].final_image_url\`.
|
|
1245
|
+
**If you request a human model** (\`controls.model.presence\` is not \`none\`) you MUST pass
|
|
1246
|
+
\`attestation_accepted: true\` to confirm the user has the rights for model imagery.
|
|
1247
|
+
- \`get_product_photo_generation { generation_id }\` — poll until \`status\` is \`complete\`,
|
|
1248
|
+
\`partial_failure\`, or \`failed\`. Each \`outputs[]\` entry has its own \`status\` and, once ready, a
|
|
1249
|
+
\`final_image_url\`. A \`flagged\` output is the best attempt but wasn't billed.
|
|
1250
|
+
|
|
1251
|
+
**Use the results**
|
|
1252
|
+
- \`list_product_photos { brand_id, archived? }\` — the brand's generated photos (\`archived: false\`
|
|
1253
|
+
= active, \`true\` = archived).
|
|
1254
|
+
- \`approve_product_photo { output_id }\` — approve a photo: links it to the product and makes it
|
|
1255
|
+
available in the **brand kit**, so \`goose-ads\` can use it. **Photos are not used anywhere until
|
|
1256
|
+
approved.**
|
|
1257
|
+
- \`archive_product_photo { output_id, reason? }\` — archive a photo; archived photos are **excluded**
|
|
1258
|
+
from ad generation.
|
|
1259
|
+
|
|
1260
|
+
## Workflow — shoot a product
|
|
1261
|
+
|
|
1262
|
+
1. **Load the brand context** (\`brand_get_context\`, or reuse what the router passed you) and
|
|
1263
|
+
**resolve the brand + product.** \`list_ad_brands\` → \`brand_id\`. \`list_brand_products\` → pick a
|
|
1264
|
+
\`product_id\` from the catalog you already know about. If the product genuinely isn't there,
|
|
1265
|
+
\`import_product\` (poll \`get_product_import\`).
|
|
1266
|
+
2. **Quote the cost.** \`estimate_product_photos { count, quality }\` → tell the user credits.
|
|
1267
|
+
3. **Generate.** \`generate_product_photos { brand_id, product_id, category, count, quality, prompt? }\`.
|
|
1268
|
+
Build \`prompt\` from the brand's voice/positioning you already have — don't interview the user for it.
|
|
1269
|
+
Returns a generation \`id\` right away.
|
|
1270
|
+
4. **Poll.** \`get_product_photo_generation { generation_id }\` until terminal; hand back each
|
|
1271
|
+
\`final_image_url\`.
|
|
1272
|
+
5. **Approve the keepers.** Show the results and let the user pick; \`approve_product_photo\` the ones
|
|
1273
|
+
they'd publish (that's what puts them in the brand kit for ads), \`archive_product_photo\` the rest.
|
|
1274
|
+
|
|
1275
|
+
## Rules
|
|
1276
|
+
|
|
1277
|
+
- **Never invent product facts.** The backend grounds the shot on the product's real images; don't
|
|
1278
|
+
describe a product you can't see.
|
|
1279
|
+
- **Use the brand context instead of interviewing the user.** Product, audience, voice, positioning,
|
|
1280
|
+
logo/colors/fonts all come from \`brand_get_context\` / the brand kit. Ask only for the shot
|
|
1281
|
+
category, count, quality, and model consent.
|
|
1282
|
+
- **Ask before spending.** Quote the estimate and confirm \`count\` / \`quality\` before
|
|
1283
|
+
\`generate_product_photos\` — it reserves credits.
|
|
1284
|
+
- **Poll, don't re-submit.** A generation that's still \`running\` is not stuck; re-submitting
|
|
1285
|
+
double-bills. Only a \`failed\` generation should be retried.
|
|
1286
|
+
- **Model imagery needs consent.** Only set a human model when the user asks, and pass
|
|
1287
|
+
\`attestation_accepted: true\`.
|
|
1288
|
+
- **Approval is the hand-off to ads.** Remind the user that only **approved** photos reach the brand
|
|
1289
|
+
kit / ad workflow; archived ones never do.
|
|
1290
|
+
`;
|
|
1291
|
+
}
|
|
1107
1292
|
//# sourceMappingURL=master-skill.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"master-skill.js","sourceRoot":"","sources":["../../src/skills/master-skill.ts"],"names":[],"mappings":"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"}
|
package/dist/skills/names.d.ts
CHANGED
|
@@ -1,2 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Which directories under ~/.agents/skills/ the CLI is allowed to DELETE.
|
|
3
|
+
*
|
|
4
|
+
* GOOSE-3191 (data loss): this predicate used to match ANY directory whose name
|
|
5
|
+
* started with `goose-` or `gooseworks-`. `gooseworks install` calls
|
|
6
|
+
* `removeAllSkills()` on every install / update / login-refresh, so a user's own
|
|
7
|
+
* unrelated third-party skill — `goose-notes`, `goose-jira`, anything they wrote
|
|
8
|
+
* themselves — was silently destroyed. A name prefix is NOT ownership.
|
|
9
|
+
*
|
|
10
|
+
* The rule now, in order of authority:
|
|
11
|
+
*
|
|
12
|
+
* 1. **Known entry-skill slugs** (`gooseworks`, `goose-ads`, `goose-video`,
|
|
13
|
+
* `goose-product-photos`, plus the legacy `ads-remix` name) are ours by
|
|
14
|
+
* definition — they are the dirs the CLI itself writes on every install, so
|
|
15
|
+
* we delete them regardless of whether they carry a stamp. This is what
|
|
16
|
+
* keeps upgrades from an old CLI working.
|
|
17
|
+
* 2. **A `.gooseworks-version` stamp** marks a directory the installer wrote.
|
|
18
|
+
* It is a SECONDARY signal, used to recognise standalone skills installed
|
|
19
|
+
* with `--with <slug>` (whose slugs we can't enumerate ahead of time).
|
|
20
|
+
* 3. **Anything else is the user's.** An unstamped directory that is not a
|
|
21
|
+
* known entry slug is NEVER deleted, no matter what it's called.
|
|
22
|
+
*
|
|
23
|
+
* Deliberate, documented trade-off: a standalone skill installed by an OLDER CLI
|
|
24
|
+
* (before `installStandaloneSkill` wrote a stamp) is unstamped and therefore no
|
|
25
|
+
* longer removed by `removeAllSkills()`. That is the safe direction to be wrong —
|
|
26
|
+
* it leaves a stale-but-working copy on disk instead of deleting a stranger's
|
|
27
|
+
* work — and it self-heals: re-running `gooseworks install --with <slug>`
|
|
28
|
+
* replaces the directory in place and stamps it.
|
|
29
|
+
*/
|
|
30
|
+
/** The stamp file `installEntrySkill` / `installStandaloneSkill` write. */
|
|
31
|
+
export declare const STAMP_FILE = ".gooseworks-version";
|
|
32
|
+
/**
|
|
33
|
+
* Entry-skill dir names the CLI no longer writes but must still clean up.
|
|
34
|
+
* `ads-remix` was renamed to `goose-ads`.
|
|
35
|
+
*/
|
|
36
|
+
export declare const LEGACY_ENTRY_SKILL_NAMES: readonly ["ads-remix"];
|
|
37
|
+
/**
|
|
38
|
+
* Every skill directory name the CLI itself owns and writes. Derived from
|
|
39
|
+
* `getEntrySkills()` so the registry stays the single source (GOOSE-3190).
|
|
40
|
+
*/
|
|
41
|
+
export declare function getManagedEntrySkillNames(): string[];
|
|
42
|
+
/** True when `name` is a skill directory the CLI itself installs. */
|
|
43
|
+
export declare function isManagedEntrySkillName(name: string): boolean;
|
|
44
|
+
/** True when `<skillsBase>/<name>/.gooseworks-version` exists. */
|
|
45
|
+
export declare function hasGooseworksStamp(skillsBase: string, name: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* True when the CLI may manage (link, list, and DELETE) `<skillsBase>/<name>/`.
|
|
48
|
+
*
|
|
49
|
+
* `skillsBase` is required: ownership is a property of what's ON DISK, not of
|
|
50
|
+
* the name. Callers that only have a name (e.g. pruning symlinks in
|
|
51
|
+
* ~/.claude/skills) pass the skills base the links point into.
|
|
52
|
+
*/
|
|
53
|
+
export declare function isManagedGooseworksSkill(name: string, skillsBase: string): boolean;
|
|
2
54
|
//# sourceMappingURL=names.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../src/skills/names.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"names.d.ts","sourceRoot":"","sources":["../../src/skills/names.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,UAAU,wBAAwB,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,wBAAwB,wBAAyB,CAAC;AAE/D;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAEpD;AAED,qEAAqE;AACrE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAM5E;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAGlF"}
|
package/dist/skills/names.js
CHANGED
|
@@ -1,12 +1,112 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.LEGACY_ENTRY_SKILL_NAMES = exports.STAMP_FILE = void 0;
|
|
37
|
+
exports.getManagedEntrySkillNames = getManagedEntrySkillNames;
|
|
38
|
+
exports.isManagedEntrySkillName = isManagedEntrySkillName;
|
|
39
|
+
exports.hasGooseworksStamp = hasGooseworksStamp;
|
|
3
40
|
exports.isManagedGooseworksSkill = isManagedGooseworksSkill;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const master_skill_1 = require("./master-skill");
|
|
44
|
+
/**
|
|
45
|
+
* Which directories under ~/.agents/skills/ the CLI is allowed to DELETE.
|
|
46
|
+
*
|
|
47
|
+
* GOOSE-3191 (data loss): this predicate used to match ANY directory whose name
|
|
48
|
+
* started with `goose-` or `gooseworks-`. `gooseworks install` calls
|
|
49
|
+
* `removeAllSkills()` on every install / update / login-refresh, so a user's own
|
|
50
|
+
* unrelated third-party skill — `goose-notes`, `goose-jira`, anything they wrote
|
|
51
|
+
* themselves — was silently destroyed. A name prefix is NOT ownership.
|
|
52
|
+
*
|
|
53
|
+
* The rule now, in order of authority:
|
|
54
|
+
*
|
|
55
|
+
* 1. **Known entry-skill slugs** (`gooseworks`, `goose-ads`, `goose-video`,
|
|
56
|
+
* `goose-product-photos`, plus the legacy `ads-remix` name) are ours by
|
|
57
|
+
* definition — they are the dirs the CLI itself writes on every install, so
|
|
58
|
+
* we delete them regardless of whether they carry a stamp. This is what
|
|
59
|
+
* keeps upgrades from an old CLI working.
|
|
60
|
+
* 2. **A `.gooseworks-version` stamp** marks a directory the installer wrote.
|
|
61
|
+
* It is a SECONDARY signal, used to recognise standalone skills installed
|
|
62
|
+
* with `--with <slug>` (whose slugs we can't enumerate ahead of time).
|
|
63
|
+
* 3. **Anything else is the user's.** An unstamped directory that is not a
|
|
64
|
+
* known entry slug is NEVER deleted, no matter what it's called.
|
|
65
|
+
*
|
|
66
|
+
* Deliberate, documented trade-off: a standalone skill installed by an OLDER CLI
|
|
67
|
+
* (before `installStandaloneSkill` wrote a stamp) is unstamped and therefore no
|
|
68
|
+
* longer removed by `removeAllSkills()`. That is the safe direction to be wrong —
|
|
69
|
+
* it leaves a stale-but-working copy on disk instead of deleting a stranger's
|
|
70
|
+
* work — and it self-heals: re-running `gooseworks install --with <slug>`
|
|
71
|
+
* replaces the directory in place and stamps it.
|
|
72
|
+
*/
|
|
73
|
+
/** The stamp file `installEntrySkill` / `installStandaloneSkill` write. */
|
|
74
|
+
exports.STAMP_FILE = '.gooseworks-version';
|
|
75
|
+
/**
|
|
76
|
+
* Entry-skill dir names the CLI no longer writes but must still clean up.
|
|
77
|
+
* `ads-remix` was renamed to `goose-ads`.
|
|
78
|
+
*/
|
|
79
|
+
exports.LEGACY_ENTRY_SKILL_NAMES = ['ads-remix'];
|
|
80
|
+
/**
|
|
81
|
+
* Every skill directory name the CLI itself owns and writes. Derived from
|
|
82
|
+
* `getEntrySkills()` so the registry stays the single source (GOOSE-3190).
|
|
83
|
+
*/
|
|
84
|
+
function getManagedEntrySkillNames() {
|
|
85
|
+
return [...(0, master_skill_1.getEntrySkillNames)(), ...exports.LEGACY_ENTRY_SKILL_NAMES];
|
|
86
|
+
}
|
|
87
|
+
/** True when `name` is a skill directory the CLI itself installs. */
|
|
88
|
+
function isManagedEntrySkillName(name) {
|
|
89
|
+
return getManagedEntrySkillNames().includes(name);
|
|
90
|
+
}
|
|
91
|
+
/** True when `<skillsBase>/<name>/.gooseworks-version` exists. */
|
|
92
|
+
function hasGooseworksStamp(skillsBase, name) {
|
|
93
|
+
try {
|
|
94
|
+
return fs.existsSync(path.join(skillsBase, name, exports.STAMP_FILE));
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* True when the CLI may manage (link, list, and DELETE) `<skillsBase>/<name>/`.
|
|
102
|
+
*
|
|
103
|
+
* `skillsBase` is required: ownership is a property of what's ON DISK, not of
|
|
104
|
+
* the name. Callers that only have a name (e.g. pruning symlinks in
|
|
105
|
+
* ~/.claude/skills) pass the skills base the links point into.
|
|
106
|
+
*/
|
|
107
|
+
function isManagedGooseworksSkill(name, skillsBase) {
|
|
108
|
+
if (isManagedEntrySkillName(name))
|
|
109
|
+
return true;
|
|
110
|
+
return hasGooseworksStamp(skillsBase, name);
|
|
11
111
|
}
|
|
12
112
|
//# sourceMappingURL=names.js.map
|
package/dist/skills/names.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/skills/names.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"names.js","sourceRoot":"","sources":["../../src/skills/names.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,8DAEC;AAGD,0DAEC;AAGD,gDAMC;AASD,4DAGC;AA3ED,uCAAyB;AACzB,2CAA6B;AAC7B,iDAAoD;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,2EAA2E;AAC9D,QAAA,UAAU,GAAG,qBAAqB,CAAC;AAEhD;;;GAGG;AACU,QAAA,wBAAwB,GAAG,CAAC,WAAW,CAAU,CAAC;AAE/D;;;GAGG;AACH,SAAgB,yBAAyB;IACvC,OAAO,CAAC,GAAG,IAAA,iCAAkB,GAAE,EAAE,GAAG,gCAAwB,CAAC,CAAC;AAChE,CAAC;AAED,qEAAqE;AACrE,SAAgB,uBAAuB,CAAC,IAAY;IAClD,OAAO,yBAAyB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,kEAAkE;AAClE,SAAgB,kBAAkB,CAAC,UAAkB,EAAE,IAAY;IACjE,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,kBAAU,CAAC,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,wBAAwB,CAAC,IAAY,EAAE,UAAkB;IACvE,IAAI,uBAAuB,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAC9C,CAAC"}
|