Initial JAE-IMAGE-SKILL rebrand

This commit is contained in:
JaeSwift Bot 2026-05-01 04:05:47 +00:00
commit 5c1694ffb9
23 changed files with 194412 additions and 0 deletions

5
.clawhubignore Normal file
View file

@ -0,0 +1,5 @@
node_modules/
dist/
.env
.git/
pnpm-lock.yaml

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
node_modules/
dist/
.env
references/.last-updated

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 YouMind-OpenLab
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

12
NOTICE Normal file
View file

@ -0,0 +1,12 @@
JAE-IMAGE-SKILL NOTICE
======================
JAE-IMAGE-SKILL is a JaeSwift-maintained derivative of the MIT-licensed
ai-image-prompts-skill project originally published by YouMind-OpenLab.
The original MIT copyright notice is retained in LICENSE as required by the
licence. JaeSwift modifications include rebranding, installer documentation,
Agent Zero/generic-agent installation guidance, JAE-controlled reference
hosting, and public install instructions.
Additional modifications Copyright (c) 2026 JaeSwift.

82
README.md Normal file
View file

@ -0,0 +1,82 @@
# JAE-IMAGE-SKILL — Curated Image Prompt Recommender for AI Agents
JAE-IMAGE-SKILL is an installable AI-agent skill for finding, recommending, and customising proven image-generation prompts. It works with Agent Zero / Agent JAE, Claude-style skill loaders, Cursor, Codex, Gemini CLI, Windsurf, and other agents that can read a `SKILL.md` file and local JSON references.
The skill is model-agnostic. The prompts can be adapted for Midjourney, DALL-E, GPT Image, Flux, Stable Diffusion, Gemini image models, Seedream, and other text-to-image systems.
## Canonical install link
Give this URL to an AI agent and tell it to install the skill:
```text
https://jaeswift.xyz/skills/JAE-image-skill/Jae-Image-Skill.MD
```
The installer markdown explains how to clone or download the skill, where to place it, how to validate it, and how to use it.
## Repository contents
```text
jae-image-skill/
SKILL.md # instructions loaded by the AI agent
package.json # optional Node package metadata + setup scripts
scripts/setup.js # refreshes reference JSON from JaeSwift static hosting
references/manifest.json # dynamic category manifest
references/*.json # prompt reference data
LICENSE # MIT licence retained from upstream
NOTICE # derivative/provenance notice
```
## Quick manual install
```bash
SKILLS_DIR="${SKILLS_DIR:-$HOME/.agent-zero/skills}"
mkdir -p "$SKILLS_DIR"
git clone https://github.com/JaeSwift/JAE-IMAGE-SKILL.git "$SKILLS_DIR/jae-image-skill"
cd "$SKILLS_DIR/jae-image-skill"
node scripts/setup.js --check || node scripts/setup.js
```
If your agent uses a different skills root, install the folder there instead. The required file is `SKILL.md`; the references are JSON files under `references/`.
## Usage examples
Ask your agent:
```text
Use JAE Image Skill to find a cyberpunk avatar prompt with sample images.
```
```text
Use JAE Image Skill to find three YouTube thumbnail prompt styles for a Solana market update video.
```
```text
Here is my article. Use JAE Image Skill to recommend a matching cover-image prompt, then remix it for my topic.
```
The agent should return up to three prompt recommendations with sample image URLs and a concise reason each one matches.
## Reference refresh
References are hosted under:
```text
https://jaeswift.xyz/skills/JAE-image-skill/references/
```
Refresh manually:
```bash
node scripts/setup.js --force
```
Override the source if mirroring elsewhere:
```bash
JAE_IMAGE_SKILL_BASE_URL=https://example.com/references node scripts/setup.js --force
```
## Licence
MIT. This is a JaeSwift-maintained derivative of an MIT-licensed upstream project. The original copyright notice is retained in `LICENSE`; derivative details are in `NOTICE`.

234
SKILL.md Normal file
View file

@ -0,0 +1,234 @@
---
name: jae-image-skill
description: |
Recommend curated image-generation prompts from a large local JSON prompt library.
Works with any text-to-image model: Midjourney, DALL-E, GPT Image, Flux, Stable Diffusion,
Gemini image models, Seedream, and others.
Use this skill when users want to:
- Find proven image-generation prompts
- Get prompt inspiration for portraits, products, social posts, posters, thumbnails, UI mockups, game assets, comics, infographics, or marketing content
- Create illustrations for articles, videos, podcasts, or campaigns
- Browse categorized prompt templates with sample images
- Translate, remix, or adapt prompt techniques for a target model
platforms:
- agent-zero
- agent-jae
- claude-code
- cursor
- codex
- gemini-cli
- generic-agent
---
# JAE Image Skill — Universal Image Prompt Recommender
You are an expert at recommending image-generation prompts from the local JAE Image Skill reference library. The prompts are model-agnostic and can be adapted for Midjourney, DALL-E, GPT Image, Flux, Stable Diffusion, Gemini image models, Seedream, and other text-to-image systems.
## Critical rule: sample images are mandatory
Every prompt recommendation must include at least one sample image URL when available.
- Each prompt usually has `sourceMedia[]`.
- Prefer `sourceMedia[0]` as the preview image.
- If a prompt has no usable sample image, skip it unless there are no better matches.
- Never present recommendations as text-only when sample images exist.
## Quick workflow
User need → read manifest → choose likely categories → search JSON references efficiently → recommend up to 3 prompt matches with sample images → optionally remix the chosen prompt for the users specific subject/model.
## Setup check
The skill directory is the folder containing this `SKILL.md` file. References should exist in:
```text
references/manifest.json
references/*.json
```
If references are missing or stale, run:
```bash
node <skill_dir>/scripts/setup.js --check
```
To force-refresh from JaeSwift hosting:
```bash
node <skill_dir>/scripts/setup.js --force
```
The default reference source is:
```text
https://jaeswift.xyz/skills/JAE-image-skill/references
```
## Available reference files
Do not hardcode categories. Always read `references/manifest.json` first. It contains:
```json
{
"updatedAt": "...",
"totalPrompts": 12837,
"categories": [
{ "slug": "social-media-post", "title": "Social Media Post", "file": "social-media-post.json", "count": 7972 }
]
}
```
Current common categories include:
- Profile / Avatar
- Social Media Post
- Infographic / Edu Visual
- YouTube Thumbnail
- Comic / Storyboard
- Product Marketing
- E-commerce Main Image
- Game Asset
- Poster / Flyer
- App / Web Design
- Uncategorized
## Category matching guidance
After reading the manifest, infer the best file from category titles:
- avatar, profile, headshot, selfie → Profile / Avatar
- infographic, diagram, chart, educational visual → Infographic / Edu Visual
- youtube, thumbnail, video cover → YouTube Thumbnail
- product, ad, promo, campaign, marketing → Product Marketing
- poster, flyer, banner, event → Poster / Flyer
- e-commerce, product photo, listing → E-commerce Main Image
- game, sprite, character, asset → Game Asset
- comic, manga, storyboard → Comic / Storyboard
- app, UI, web, dashboard, interface → App / Web Design
- instagram, twitter, x post, linkedin, social → Social Media Post
- unclear or experimental → Uncategorized and/or search multiple files
## Token and performance rules
Never load entire large category JSON files into model context.
Use terminal tools, grep, jq, ripgrep, a short script, or streaming JSON search. Load only the matching records you need.
Recommended search process:
1. Read `references/manifest.json`.
2. Pick one to three likely category files.
3. Search for keywords from the user request.
4. Score matches by title, description, content, category relevance, and presence of sample images.
5. Return up to 3 best matches.
Example shell search:
```bash
cd <skill_dir>
rg -i "cyberpunk|avatar|neon|portrait" references/profile-avatar.json references/others.json
```
Example Node extraction:
```bash
node - <<'NODE'
const fs = require('fs');
const files = ['references/profile-avatar.json', 'references/others.json'];
const terms = ['cyberpunk', 'avatar', 'neon', 'portrait'];
for (const file of files) {
const arr = JSON.parse(fs.readFileSync(file, 'utf8'));
for (const p of arr) {
const hay = `${p.title} ${p.description} ${p.content}`.toLowerCase();
const score = terms.reduce((n,t)=>n+(hay.includes(t)?1:0),0);
if (score >= 2 && Array.isArray(p.sourceMedia) && p.sourceMedia.length) {
console.log(JSON.stringify({file, score, id:p.id, title:p.title, image:p.sourceMedia[0], prompt:p.content.slice(0,500)}));
}
}
}
NODE
```
## Clarify vague requests
Ask a short clarification if the request is too broad to search well. Minimum useful context:
- image type: avatar, cover, product photo, thumbnail, poster, etc.
- subject/topic: what the image represents
- desired style/mood/audience, if relevant
Examples:
- “I need a portrait” → ask realistic/anime/editorial/cyberpunk, who/what, mood.
- “Make an infographic” → ask topic/data/process/timeline/comparison.
- “Generate a product photo” → ask product, background, use case.
- “Illustrate my content” → ask preferred visual style and target audience if not obvious.
## Direct search mode
Use when the user describes the desired image.
Return up to 3 recommendations. For each recommendation include:
- title
- category/file
- why it matches
- sample image URL
- prompt preview
- full prompt or enough of the prompt to be useful
- suggested adaptation notes for the users model, if needed
## Content illustration mode
Use when the user provides article text, video script, podcast notes, product copy, campaign notes, or a concept to illustrate.
Process:
1. Identify the content theme, tone, audience, and required format.
2. Search for visual styles that fit the content.
3. Recommend up to 3 style/prompt candidates with sample images.
4. If the user selects one, remix the prompt by inserting the users actual topic, brand, product, article title, or scene details.
5. Keep the final generation prompt in English unless the user specifically wants another language.
## Output format
Use a concise structure:
```markdown
## JAE Image Skill recommendations
### 1. <Title>
- **Best for:** <use case>
- **Why it matches:** <reason>
- **Sample image:** <url>
- **Prompt:** <prompt or useful excerpt>
- **Adaptation notes:** <optional>
```
If your platform supports image attachments or markdown images, show the sample image inline:
```markdown
![sample](<sourceMedia[0]>)
```
## Model adaptation rules
- Remove model-specific flags that the target model does not support.
- Convert aspect-ratio syntax when needed.
- Preserve the visual composition, subject, lighting, camera/style language, and negative constraints.
- For brand or character consistency, ask for reference images if the prompt requires them.
- If the prompt mentions reference images but the user has not supplied any, clearly say a reference image is needed or adapt the prompt to work without one.
## No-match fallback
If no strong match is found:
1. Say no strong library match was found.
2. Offer the closest 12 partial matches if useful.
3. Create a custom prompt from scratch using the same techniques seen in the library.
4. Ask one targeted clarification if needed.
## Licence note
This skill is distributed under MIT. It is a JaeSwift-maintained derivative of an MIT-licensed upstream project. Keep `LICENSE` and `NOTICE` with the skill package.

4
_meta.json Normal file
View file

@ -0,0 +1,4 @@
{
"ownerId": "jaeswift",
"slug": "jae-image-skill"
}

44
package.json Normal file
View file

@ -0,0 +1,44 @@
{
"name": "jae-image-skill",
"version": "1.0.0",
"description": "JAE Image Skill: an installable AI-agent skill for finding, recommending, and customising curated image-generation prompts with sample images for any text-to-image model.",
"type": "module",
"scripts": {
"postinstall": "node scripts/setup.js",
"setup": "node scripts/setup.js",
"sync": "node scripts/setup.js --force"
},
"keywords": [
"jaeswift",
"jae-image-skill",
"agent-zero",
"agent-jae",
"ai-agent-skill",
"image-generation",
"prompt-library",
"prompt-engineering",
"prompt-templates",
"image-prompts",
"text-to-image",
"ai-art",
"ai-image",
"midjourney-prompts",
"dall-e-prompts",
"flux-prompts",
"stable-diffusion-prompts",
"gpt-image",
"gemini-image",
"content-creation",
"image-prompt-recommend"
],
"author": "JaeSwift",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/JaeSwift/JAE-IMAGE-SKILL.git"
},
"homepage": "https://jaeswift.xyz/skills/JAE-image-skill/",
"bugs": {
"url": "https://github.com/JaeSwift/JAE-IMAGE-SKILL/issues"
}
}

171
public/Jae-Image-Skill.MD Normal file
View file

@ -0,0 +1,171 @@
# JAE Image Skill — Agent Install File
This markdown file is designed for AI agents to read and execute. Install the JAE Image Skill into the users local skills directory, then load `SKILL.md` whenever the user asks for image-prompt recommendations.
## Identity
- Human name: **JAE Image Skill**
- Canonical package/repo name: **JAE-IMAGE-SKILL**
- Local skill folder name: **jae-image-skill**
- Purpose: recommend and customise curated image-generation prompts with sample images for any text-to-image model.
- Canonical install document: `https://jaeswift.xyz/skills/JAE-image-skill/Jae-Image-Skill.MD`
- Canonical reference base: `https://jaeswift.xyz/skills/JAE-image-skill/references`
- Preferred Git repo: `https://github.com/JaeSwift/JAE-IMAGE-SKILL.git`
## Compatibility
Use this for:
- Agent Zero / Agent JAE
- Claude-style skills
- Cursor/Codex/Gemini CLI/Windsurf-style local agents
- Any agent that can read a `SKILL.md` file and local JSON references
## Required runtime
- Node.js 18+ minimum; Node.js 20+ recommended.
- `git`, `curl`, and `bash` recommended.
- `pnpm` is optional and only needed for development scripts.
## Installation algorithm for the AI agent
### Step 1 — choose skills root
Prefer the users configured skills directory. If unknown, use one of these common locations:
```bash
# Agent Zero / Agent JAE common user-space path inside container:
/a0/usr/skills
# Generic local fallback:
$HOME/.agent-zero/skills
# Generic agent fallback:
$HOME/.ai/skills
```
Use this shell pattern if no configured directory is known:
```bash
if [ -d /a0/usr/skills ]; then
SKILLS_DIR=/a0/usr/skills
elif [ -d "$HOME/.agent-zero/skills" ]; then
SKILLS_DIR="$HOME/.agent-zero/skills"
else
SKILLS_DIR="$HOME/.ai/skills"
fi
export SKILLS_DIR
```
### Step 2 — install from Git
```bash
set -euo pipefail
: "${SKILLS_DIR:=${HOME}/.ai/skills}"
SKILL_DIR="$SKILLS_DIR/jae-image-skill"
mkdir -p "$SKILLS_DIR"
if [ -d "$SKILL_DIR/.git" ]; then
git -C "$SKILL_DIR" pull --ff-only
else
rm -rf "$SKILL_DIR"
git clone https://github.com/JaeSwift/JAE-IMAGE-SKILL.git "$SKILL_DIR"
fi
cd "$SKILL_DIR"
node scripts/setup.js --check || node scripts/setup.js
```
### Step 3 — fallback install without Git
If GitHub access fails, download the static bundle from JaeSwift hosting:
```bash
set -euo pipefail
: "${SKILLS_DIR:=${HOME}/.ai/skills}"
mkdir -p "$SKILLS_DIR"
cd "$SKILLS_DIR"
rm -rf jae-image-skill
curl -fsSL https://jaeswift.xyz/skills/JAE-image-skill/jae-image-skill.tar.gz | tar -xz
cd jae-image-skill
node scripts/setup.js --check || true
```
### Step 4 — validate install
```bash
set -euo pipefail
cd "$SKILLS_DIR/jae-image-skill"
test -s SKILL.md
test -s package.json
test -s scripts/setup.js
test -s references/manifest.json
node - <<'NODE'
const fs = require('fs');
const m = JSON.parse(fs.readFileSync('references/manifest.json','utf8'));
if (!Array.isArray(m.categories) || m.categories.length === 0) throw new Error('No categories in manifest');
if (typeof m.totalPrompts !== 'number') throw new Error('Bad totalPrompts');
for (const c of m.categories) {
if (!c.file || !fs.existsSync(`references/${c.file}`)) throw new Error(`Missing ${c.file}`);
const arr = JSON.parse(fs.readFileSync(`references/${c.file}`,'utf8'));
if (!Array.isArray(arr) || arr.length !== c.count) throw new Error(`Bad count for ${c.file}`);
}
console.log(`JAE Image Skill OK: ${m.categories.length} categories, ${m.totalPrompts} unique prompts`);
NODE
```
## How the installed agent should use the skill
1. Read `SKILL.md`.
2. Read `references/manifest.json` first.
3. Pick relevant category files from the manifest.
4. Do **not** load huge JSON files wholesale into model context.
5. Search using `rg`, `grep`, `jq`, Node.js, Python, or streaming JSON parsing.
6. Return up to 3 prompt recommendations.
7. Include sample image URLs from `sourceMedia[0]` whenever available.
8. If the user supplies article/script/product/brand context, remix the selected prompt around that content.
## Minimum file layout after install
```text
jae-image-skill/
SKILL.md
README.md
package.json
LICENSE
NOTICE
scripts/setup.js
references/manifest.json
references/*.json
```
## Refresh references
```bash
cd "$SKILLS_DIR/jae-image-skill"
node scripts/setup.js --force
```
The default refresh source is:
```text
https://jaeswift.xyz/skills/JAE-image-skill/references
```
To use a mirror:
```bash
JAE_IMAGE_SKILL_BASE_URL=https://example.com/references node scripts/setup.js --force
```
## Troubleshooting
- `node: fetch is not defined` — upgrade to Node.js 18+; Node.js 20+ recommended.
- `HTTP 404` — check URL case. The public path is case-sensitive: `/skills/JAE-image-skill/`.
- `references/manifest.json missing` — run `node scripts/setup.js --force`, or install from the tarball which includes bundled references.
- Network-blocked environment — use the bundled tarball and skip live refresh.
- Agent cannot find the skill — confirm the folder is named `jae-image-skill` and contains `SKILL.md` at the top level.
## Licence
JAE-IMAGE-SKILL is distributed under the MIT licence. It is a JaeSwift-maintained derivative of an MIT-licensed upstream project. The original copyright notice is retained in `LICENSE` and derivative information is provided in `NOTICE`.

0
references/.gitkeep Normal file
View file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

5916
references/game-asset.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

72
references/manifest.json Normal file
View file

@ -0,0 +1,72 @@
{
"updatedAt": "2026-05-01T01:59:02.889Z",
"totalPrompts": 12837,
"categories": [
{
"slug": "profile-avatar",
"title": "Profile / Avatar",
"file": "profile-avatar.json",
"count": 1386
},
{
"slug": "social-media-post",
"title": "Social Media Post",
"file": "social-media-post.json",
"count": 7972
},
{
"slug": "infographic-edu-visual",
"title": "Infographic / Edu Visual",
"file": "infographic-edu-visual.json",
"count": 531
},
{
"slug": "youtube-thumbnail",
"title": "YouTube Thumbnail",
"file": "youtube-thumbnail.json",
"count": 203
},
{
"slug": "comic-storyboard",
"title": "Comic / Storyboard",
"file": "comic-storyboard.json",
"count": 402
},
{
"slug": "product-marketing",
"title": "Product Marketing",
"file": "product-marketing.json",
"count": 4715
},
{
"slug": "ecommerce-main-image",
"title": "E-commerce Main Image",
"file": "ecommerce-main-image.json",
"count": 509
},
{
"slug": "game-asset",
"title": "Game Asset",
"file": "game-asset.json",
"count": 545
},
{
"slug": "poster-flyer",
"title": "Poster / Flyer",
"file": "poster-flyer.json",
"count": 642
},
{
"slug": "app-web-design",
"title": "App / Web Design",
"file": "app-web-design.json",
"count": 195
},
{
"slug": "others",
"title": "Uncategorized",
"file": "others.json",
"count": 1045
}
]
}

11156
references/others.json Normal file

File diff suppressed because one or more lines are too long

6824
references/poster-flyer.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

14611
references/profile-avatar.json Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

119
scripts/setup.js Executable file
View file

@ -0,0 +1,119 @@
#!/usr/bin/env node
/**
* setup.js - Downloads/updates the JAE Image Skill reference library.
*
* Fully dynamic: reads manifest.json first to discover all categories.
* New/renamed/removed categories are handled automatically no hardcoding.
*
* Usage:
* node scripts/setup.js # Download missing files only
* node scripts/setup.js --force # Force re-download all references
* node scripts/setup.js --check # Auto-update if stale (> 24h)
*
* Override source if needed:
* JAE_IMAGE_SKILL_BASE_URL=https://example.com/references node scripts/setup.js --force
*/
import { existsSync, mkdirSync, statSync, writeFileSync, readFileSync, readdirSync, unlinkSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const refsDir = join(__dirname, '..', 'references');
const stampFile = join(refsDir, '.last-updated');
const BASE_URL = (process.env.JAE_IMAGE_SKILL_BASE_URL || 'https://jaeswift.xyz/skills/JAE-image-skill/references').replace(/\/$/, '');
const STALE_HOURS = Number(process.env.JAE_IMAGE_SKILL_STALE_HOURS || 24);
function isStale() {
if (!existsSync(stampFile)) return true;
const ts = parseInt(readFileSync(stampFile, 'utf8').trim(), 10);
return (Date.now() - ts) / 1000 / 3600 > STALE_HOURS;
}
async function fetchText(url) {
if (typeof fetch !== 'function') {
throw new Error('This installer requires Node.js 18+ with global fetch. Node 20+ is recommended.');
}
const res = await fetch(url);
if (!res.ok) throw new Error(`HTTP ${res.status}${url}`);
return res.text();
}
async function setup() {
const args = process.argv.slice(2);
const forceMode = args.includes('--force');
const checkMode = args.includes('--check');
if (checkMode && !isStale()) {
return;
}
if (!existsSync(refsDir)) mkdirSync(refsDir, { recursive: true });
const label = forceMode ? 'Updating' : 'Downloading';
console.log(`[setup] ${label} JAE Image Skill reference library from ${BASE_URL} ...`);
let categories;
try {
const manifestText = await fetchText(`${BASE_URL}/manifest.json`);
const manifest = JSON.parse(manifestText);
categories = manifest.categories;
if (!Array.isArray(categories) || categories.length === 0) throw new Error('manifest has no categories');
writeFileSync(join(refsDir, 'manifest.json'), manifestText, 'utf8');
console.log(` manifest: ${categories.length} categories, ${manifest.totalPrompts} prompts total`);
} catch (err) {
console.warn(`[setup] Could not fetch manifest: ${err.message}`);
console.warn('[setup] Falling back to existing local manifest...');
const localManifest = join(refsDir, 'manifest.json');
if (!existsSync(localManifest)) {
console.error('[setup] No manifest available. Install from the bundled repo/archive or retry with --force.');
process.exit(0);
}
categories = JSON.parse(readFileSync(localManifest, 'utf8')).categories;
}
const validFiles = new Set([...categories.map(c => c.file), 'manifest.json', '.last-updated', '.gitkeep']);
if (forceMode && existsSync(refsDir)) {
for (const f of readdirSync(refsDir)) {
if (!validFiles.has(f)) {
unlinkSync(join(refsDir, f));
console.log(` removed stale: ${f}`);
}
}
}
let downloaded = 0, skipped = 0, failed = 0;
for (const cat of categories) {
const dest = join(refsDir, cat.file);
if (!forceMode && existsSync(dest) && statSync(dest).size > 100) {
skipped++;
continue;
}
process.stdout.write(`${cat.file} (${cat.title}, ${cat.count} prompts) ... `);
try {
const text = await fetchText(`${BASE_URL}/${cat.file}`);
JSON.parse(text);
writeFileSync(dest, text, 'utf8');
console.log('✓');
downloaded++;
} catch (err) {
console.log(`✗ (${err.message})`);
failed++;
}
}
if (failed === 0) writeFileSync(stampFile, String(Date.now()), 'utf8');
if (downloaded > 0) {
console.log(`[setup] Done! ${downloaded} file(s) ${forceMode ? 'updated' : 'downloaded'}. JAE Image Skill is ready.`);
} else if (skipped === categories.length) {
console.log('[setup] All references up to date. Use --force to refresh.');
}
if (failed > 0) console.warn(`[setup] ${failed} file(s) failed. Run again to retry.`);
}
setup().catch(err => {
console.warn('[setup] Warning (non-fatal):', err.message);
process.exit(0);
});