Skill: zoucdr/surreal-mutation-transform-video-gen-seedance2-0 (version 1.0.0)

--- name: "surreal-mutation-transform-video-gen-seedance2.0" version: 1.0.0 description: "Break reality for scroll-stopping shorts: warped space, wrong-scale objects, surprise morph payoffs—WeryAI Seedance 2.0 only. Use when you need weird bait, glitch-dream transitions, or surreal product hooks. SEO: surreal video; weird transform short video." tags: [surreal, weird, experimental, viral, short-video, video-gen] metadata: { "openclaw": { "emoji": "🫧", "primaryEnv": "WERYAI_API_KEY", "paid": true, "network_required": true, "requires": { "env": ["WERYAI_API_KEY"], "bins": ["node"], "node": ">=18" } } } user-invocable: true --- # Surreal mutation & impossible physics (Seedance 2.0) **Anti-physics storytelling:** gravity tilts, rooms fold, materials swap mid-action, scale jokes land as clear visual punchlines. **Dependencies:** `WERYAI_API_KEY` + Node.js 18+. This skill uses **only** `SEEDANCE_2_0`. When you run the CLI, **`scripts/video_gen.js`** must exist; **[`WERYAI_VIDEO_API.md`](resources/WERYAI_VIDEO_API.md)** must exist under **`resources/`** (supply both via publish or pre-use assembly). Full commands and JSON fields: see **`resources/WERYAI_VIDEO_API.md`**. **No other Cursor skills required.** ## Prerequisites - `WERYAI_API_KEY` **must be set** before running `video_gen.js`. - Node.js **18+**; prefer public **`https`** image URLs. If the assembled `scripts/video_gen.js` accepts local paths, review/verify the script and explicitly consent before local read-and-upload to WeryAI. - **Model (caller / agent):** The bundled `video_gen.js` **requires** a non-empty `model` in JSON—if `model` is missing or blank, the CLI exits with **`MISSING_PARAM`** (no default model). The script **does not** enforce this skill's allowed model in code: you **must** set `"model":"SEEDANCE_2_0"` for this package and show it in the confirmation table before submit—see [`WERYAI_VIDEO_API.md`](resources/WERYAI_VIDEO_API.md) (`model` row). - Each `wait` run may consume credits; re-run creates new paid tasks. ## Security, secrets, and API hosts - **`WERYAI_API_KEY`**: Treat as a secret. Only configure it if you trust this skill's source; it is listed in OpenClaw metadata as **`requires.env`** / **`primaryEnv`** so installers know it is mandatory at runtime (never commit it inside the skill package). - **API hosts (fixed in `video_gen.js`)**: Video tasks use **`https://api.weryai.com`**; the models list uses **`https://api-growth-agent.weryai.com`**. Child skills must not document or rely on URL environment-variable overrides—only **`WERYAI_API_KEY`** is read from the environment. - **Local image handling disclosure**: Prefer public **`https`** image URLs. If the assembled `scripts/video_gen.js` supports local file paths, it may read a local image and upload it to WeryAI to obtain a public URL; require review / verification and explicit consent before using that path. - **Higher assurance**: Run generation in a short-lived or isolated environment (separate account or container), and review `scripts/video_gen.js` (HTTPS submit + poll loop) before production use. Verify whether the runtime can read local image files and upload them to WeryAI, and obtain explicit consent before using that path. ## Prompt expansion (mandatory) `video_gen.js` does **not** expand prompts. Before every `wait --json`, turn the user's short or vague brief into a **full English production `prompt`** that **re-styles** the described event into this skill's look. **When:** User input is short, vague, or missing cinematic detail. **Exception:** They supply a finished long prompt within **2000** characters and ask you **not** to rewrite—still show the **full** text in the confirmation table. **Always add:** shot size and angle; camera move; lighting and color grade aligned to this skill; subject action paced to `duration`; **one clear payoff**; platform framing (**9:16** unless user chose another allowed ratio); if `generate_audio` is **true**, describe ambience / SFX in generic words (no copyrighted music references). **Length:** Stay within **`prompt_length_limit` 2000** for `SEEDANCE_2_0`; trim adjectives before losing the core transformation beat. **Confirmation:** The pre-submit table **must** include the **full expanded `prompt`**. ### Style transformation checklist - **Rule breaks:** melting clocks vibe, impossible stairs, duplicate reflections. - **Space warp:** corridor stretch, sky on floor—one clear hero idea per clip. - **Materials:** liquid metal, rubber stone—motivated by user beat. - **Scale play:** giant hand, tiny city—readable silhouette. - **Motion payoff:** expectation subversion in final third of timeline. - **Sound (if on):** reversed whooshes, rubbery boings—sparse and odd. **Fits:** Curiosity bait, contrast comedy, visual spectacle, pattern-interrupt ads. **`### Example prompts`** below are **richness targets only**—always derive from the user's actual brief. ## Workflow 1. Confirm the request matches this skill (text-to-video and/or single image-to-video). 2. Collect the user's **brief**, optional **`image`** URL, and tier (**best** / **good** / **fast**)—all map to **`SEEDANCE_2_0`** with different duration defaults (see **Recommended models**). 3. **Expand prompt (mandatory):** Unless the user opted out with a finished long prompt, expand using `## Prompt expansion (mandatory)`. **Do not** submit only the user's minimal words. 4. Validate **`model`** is **`SEEDANCE_2_0` only**; validate `duration`, `aspect_ratio`, `resolution`, `generate_audio` against the frozen tables. 5. Show the confirmation table with the **full expanded `prompt`**; wait for **confirm** or edits. 6. Run `node scripts/video_gen.js wait --json '...'`. 7. Parse stdout JSON; return `videos` URLs or explain errors. 8. When presenting playable URLs to the user, use **Markdown inline links only** (e.g. `[Video](https://...)`). **Do not** wrap user-facing links in code fences. ## CLI reference ~~~sh node scripts/video_gen.js wait --json '{"model":"SEEDANCE_2_0","prompt":"…","duration":10,"aspect_ratio":"9:16","resolution":"720p","generate_audio":true}' ~~~ **Full reference:** **[`WERYAI_VIDEO_API.md`](resources/WERYAI_VIDEO_API.md)**. ## Definition of done Done when the user gets at least one playable **[Video](url)**-style link, or a clear failure with next steps. Submitted `prompt` must be the **expanded** prompt unless the user explicitly opted out. **Never** use another `model_key` in this skill. ## Boundaries (out of scope) - Do not use **any model other than `SEEDANCE_2_0`** for this package. - Do not link to `weryai-model-capabilities.md` or shared `../references/` paths; use **`resources/WERYAI_VIDEO_API.md`** for CLI/API details. - Prefer public **`https`** for `image` when easy; **OpenClaw / chat attachments** are often a **local path**—if `video_gen.js` can read it, pass it as `image` and the script uploads first (use an **absolute** path if a relative path fails). Never embed the secret value of `WERYAI_API_KEY` in files. - Do not invent API fields; do not send `negative_prompt` (not supported for this model). - Do not wrap user-facing playable URLs in Markdown code fences. ### Example prompts - `Drinking coffee → cup becomes miniature swimming pool, diver splash gag, vertical` - `Walking upstairs → steps melt into waterfall, seamless dream logic` - `HTTPS sneaker → sole grows into slide, surreal playground` --- ## Model and API constraints (frozen for this skill) > Derived from `node scripts/video_gen.js models` alignment at authoring time; re-run `models` after platform upgrades. **This skill is locked to `SEEDANCE_2_0` only.** ### Text-to-video | model_key | durations | aspect_ratios | resolutions | Audio | negative_prompt | prompt limit | |-----------|-----------|---------------|-------------|-------|-----------------|---------------| | `SEEDANCE_2_0` | 5, 10, 15 | 9:16, 1:1, 16:9 | 480p, 720p | Yes | No (do not send) | 2000 | ### Image-to-video (single `image`) | model_key | durations | aspect_ratios | resolutions | Audio | negative_prompt | upload_image_limit | |-----------|-----------|---------------|-------------|-------|-----------------|-------------------| | `SEEDANCE_2_0` | 5, 10, 15 | 9:16, 1:1, 16:9 | 480p, 720p | Yes | No (do not send) | 3 | --- ## Recommended models | Tier | model_key | Notes | |------|-----------|-------| | ⭐ Best (default) | `SEEDANCE_2_0` | Prefer **`duration` 10 or 15**, **`resolution` 720p**, **`generate_audio` true** for fullest mood | | 👍 Good | `SEEDANCE_2_0` | Balanced: **`duration` 10**, **`resolution` 720p**, audio per user | | ⚡ Fast | `SEEDANCE_2_0` | Snappy: **`duration` 5**, **`resolution` 480p** or **720p**, audio optional | Tier only changes **duration / resolution / audio** defaults—**never** the model. --- ## Default parameters | Field | Value | |-------|--------| | Model | `SEEDANCE_2_0` (fixed) | | Aspect ratio | `9:16` | | Duration | `10` (use `5` for punchy; `15` for slower ceremony) | | Resolution | `720p` (`480p` allowed) | | Audio | `true` unless user wants silent | --- ## Scenario: Text-to-video style transform **Flow** 1. Capture the user's mundane event in one or two sentences. 2. Expand into English with the **Style transformation checklist**; keep identity generic unless user names a character. 3. Confirmation table → user **confirm**. 4. Execute: ~~~sh node scripts/video_gen.js wait --json '{"model":"SEEDANCE_2_0","prompt":"<expanded>","duration":10,"aspect_ratio":"9:16","resolution":"720p","generate_audio":true}' ~~~ 5. Return `[Video](url)` links. --- ## Scenario: Image-to-video style transform **Before use:** **Prefer** a public **`https://`** URL reachable from the internet. **Local paths** (e.g. OpenClaw attachment paths) work when the Node process can read them—`video_gen.js` uploads then submits; use **absolute** paths if needed. Do not use plain `http://` remote URLs. 1. Plan how the still **re-styles** in motion (props, light, environment) without breaking likeness if the user requests preservation. 2. Expand prompt; add `image` to the confirmation table. 3. After **confirm**: ~~~sh node scripts/video_gen.js wait --json '{"model":"SEEDANCE_2_0","prompt":"<expanded>","image":"https://…","duration":10,"aspect_ratio":"9:16","resolution":"720p","generate_audio":true}' ~~~ 4. Return `[Video](url)` links. --- ## Loop seam (optional) If the user asks for a **seamless loop**, append a short English trio at the **end** of the expanded prompt: `seamless loop`, `perfect loop`, `ends where it begins`—no separate API flag. > Generated for skill `surreal-mutation-transform-video-gen-seedance2.0`.

path: eval.yaml
content: version: "1"
defaults:
  trials: 3
  timeout: 600
  threshold: 0.75
skill: "surreal-mutation-transform-video-gen-seedance2.0"
trigger_tests:
  - id: explicit-invoke
    should_trigger: true
    prompt: "Use the surreal-mutation-transform-video-gen-seedance2.0 skill to transform a boring commute into a styled vertical clip."
  - id: implicit-domain
    should_trigger: true
    prompt: "Weird surreal twist: stairs melt into liquid, short vertical clip."
  - id: negative-control
    should_trigger: false
    prompt: "Refactor my Rust crate and add property-based tests only."
outcome_tests:
  - id: layout
    type: deterministic
    checks:
      - file_exists: "SKILL.md"


path: resources/WERYAI_VIDEO_API.md
content: # WeryAI video CLI & JSON (`video_gen.js`)

Shipped at **`resources/WERYAI_VIDEO_API.md`** (next to `SKILL.md`). From the skill package root, run **`node scripts/video_gen.js`** (see examples below). **Node.js 18+** required.

This file describes **CLI usage, JSON shape, and image handling**. Per-skill rules (prompt expansion, confirmation tables, allowed models) live in each skill’s **`SKILL.md`**.

---

## What you need by generation mode

The script picks the API route from your JSON:

| Mode | When | Required in JSON | API path (conceptually) |
|------|------|-------------------|-------------------------|
| **Text → video** | No `image` and no non-empty `images[]` | `model`, `prompt`, `duration` (and any optional fields the **model** supports) | `text-to-video` |
| **Image → video** | Non-empty string `image` | Same as above **plus** `image` — **must be a public `https` image URL** (see below) | `image-to-video` |
| **Multi-image → video** | Non-empty `images` array | Same as above **plus** `images` — **every element must be a public `https` image URL** | `multi-image-to-video` |

- **`model`**: required for real runs and for `--dry-run` when `prompt` is present. Empty/missing → `MISSING_PARAM` (there is **no default model**). The script does **not** enforce skill-specific model allowlists—callers must match the skill’s `SKILL.md`.
- **`prompt`**: required for `wait` and all `submit-*` flows that generate video.
- **`duration`**: sent to the API; must be one of the values allowed for the chosen model (check `models` output or the skill’s frozen table).
- Other fields (`aspect_ratio`, `resolution`, `generate_audio`, `negative_prompt`) are **only** valid if that model supports them—see `node scripts/video_gen.js models` and the skill’s **`## Model and API constraints`**.

---

## Image-to-video & multi-image: public URL requirement

For **image-to-video** (`image`) and **multi-image-to-video** (`images[]`), the value that ultimately reaches WeryAI must be a **public, directly fetchable image URL on the internet**:

- **Scheme must be `https://`** — plain **`http://` image URLs are rejected** by `video_gen.js` and must not be used.
- The URL must be reachable **from WeryAI’s servers** (not `localhost`, `127.0.0.1`, LAN-only hosts, or links that only work inside your browser session).
- Do **not** pass opaque file paths, `data:` URLs, or private object-storage links that are not already a stable public `https` address.

**Operational rule for skills and operators:** treat **public `https` image URLs as mandatory** for any image-to-video request. Host the image on a CDN, object storage with public read, or any HTTPS endpoint the API can GET without your local machine.

---

## Image input: public URL vs local path (how `video_gen.js` behaves)

### Normal path: public **https** URL (required for correct image-to-video usage)

- Put that URL in `image` (single) or each entry of `images[]` (multi).
- The script **does not** re-upload; it sends the URL straight to the video API.
- This matches the **public URL requirement** above.

### Advanced: local file → script uploads, then uses returned public URL

If `image` or an `images[]` entry is **not** already a public https URL, `video_gen.js` treats it as a **local path** (or `file://…`) and:

1. Reads the file from disk.
2. **POST**s it to **`https://api-growth-agent.weryai.com/growthai/v1/generation/upload-file`** with `Authorization: Bearer $WERYAI_API_KEY` and multipart fields `batch_no`, `fixed`, `file`.
3. Parses the response for a returned **public https** URL and substitutes that URL into the JSON sent to **video** generation — i.e. the video API still only ever sees a **public URL**; the script is just creating one from a local file.

**Implications (local path only)**

- Requires **`WERYAI_API_KEY`** with access to both **video** and **upload-file** endpoints.
- File must exist and be a **regular file**. Extensions with sensible MIME types in script: **`.jpg` / `.jpeg` / `.png` / `.webp` / `.gif`**.
- **`--dry-run`**: does **not** upload; stdout may still show local paths with a note that a real run would upload first.

**Skills / product docs:** prefer telling users to supply a **public `https` link**; use local paths only after **reviewing `video_gen.js`** and **explicit user consent** to read and upload files.

### Multi-image limits in this script

- `images` is passed through after upload resolution; the built request body keeps **at most the first 3** entries (`images.slice(0, 3)`). Models may allow fewer—always check `models` / skill tables (e.g. `upload_image_limit`).

---

## Environment

- **`WERYAI_API_KEY`** (required for `models`, generation, `status`, and local-image upload; **not** required for `--dry-run` only): bearer token. Never commit the value.
- **No other environment variables** are read. Hosts are fixed in `video_gen.js`. The **`wait`** command polls task status with **exponential backoff**: first delay **3s**, then **6s → 12s → 24s → …** (each step doubles), **capped at 60s** between polls, with a **total wall-clock budget of 600s (10 minutes)** before timeout.

## API hosts (fixed)

| Purpose | Base URL |
|---------|-----------|
| Video generation & task status | `https://api.weryai.com` |
| Model registry (`models` command) | `https://api-growth-agent.weryai.com` |
| Local file → public URL (upload) | `https://api-growth-agent.weryai.com/growthai/v1/generation/upload-file` |

---

## `models` — model metadata (JSON on stdout)

```sh
node scripts/video_gen.js models
node scripts/video_gen.js models --mode text_to_video
node scripts/video_gen.js models --mode image_to_video
node scripts/video_gen.js models --mode multi_image_to_video
```

Typical fields include `model_key`, `title`, `durations`, `aspect_ratios`, `resolutions`, `has_generate_audio`, `has_negative_prompt`, `prompt_length_limit`; image modes may add `support_multiple_images`, `support_first_last_frame`, `upload_image_limit`, etc. Use this to author **`## Model and API constraints`** in `SKILL.md`.

---

## `wait` — submit and block until done

```sh
node scripts/video_gen.js wait --json '{"model":"KLING_V3_0_PRO","prompt":"...","duration":5,"aspect_ratio":"9:16"}'
node scripts/video_gen.js wait --json '{"model":"...","prompt":"...","image":"https://cdn.example.com/pet.jpg","duration":5}'
node scripts/video_gen.js wait --json '{"model":"...","prompt":"...","images":["https://cdn.example.com/a.jpg","https://cdn.example.com/b.jpg"],"duration":5}'
# Advanced only: local paths trigger upload-file first; skills should default to public https URLs above.
node scripts/video_gen.js wait --json '{"model":"...","prompt":"...","image":"./girl.png","duration":5}'
node scripts/video_gen.js wait --json '...' --dry-run
```

Same JSON object is used for **`submit-*`**; only the blocking behavior differs.

---

## `submit-*` — submit only (async)

```sh
node scripts/video_gen.js submit-text  --json '{"model":"…","prompt":"…","duration":5}'
node scripts/video_gen.js submit-image --json '{"model":"…","prompt":"…","image":"https://…","duration":5}'
node scripts/video_gen.js submit-multi-image --json '{"model":"…","prompt":"…","images":["https://…","https://…"],"duration":5}'
# Advanced only: local file → upload then submit (same public-URL requirement for the API).
node scripts/video_gen.js submit-image --json '{"model":"…","prompt":"…","image":"./local.png","duration":5}'
```

**Note:** `submit-text`, `submit-image`, and `submit-multi-image` are **aliases** in this script: routing (text vs image vs multi-image) is decided **only** from JSON (`image` / `images`), exactly like `wait`. Use the verb that matches your intent; behavior is the same `submitTask` path aside from blocking.

Poll completion with **`status`** (below). Response JSON may include `batchId` / `taskIds` from the API; this CLI does **not** expose a separate `batch-status` subcommand.

---

## `status`

```sh
node scripts/video_gen.js status --task-id <id>
```

You may also pass a task id inside JSON as `task_id` or `taskId` when using `--json` (less common). If `--task-id` is omitted and JSON has no id, the script errors with `status command requires --task-id <id>`.

There is **no** `batch-status` command in `video_gen.js`; use per-task `status` with each `taskId` you care about. Invalid invocation prints a **Usage** line to stdout JSON (there is no `--help` flag).

---

## Agent UX: in-progress notice, task IDs, backoff polling, completion, skill name

Use this when an executor should **talk to the user** during async generation (not only return raw JSON).

1. **Right after a successful `submit-*`:** Tell the user that generation **has started** and paste **`taskId`** from stdout JSON. If the API returns **`batchId`** and/or **`taskIds`**, include those too so logs and support can correlate the job.

2. **Poll until terminal state:** Run `status --task-id <id>` repeatedly until the payload shows **completed** or **failed** (or your wrapper treats the script’s `phase` / `ok` as terminal). **Recommended delay between polls:** **3s, then 6s, then 12s, …** doubling each time, **cap at 60s**—the same pattern as **`wait`** uses inside `video_gen.js`. Stop early on success/failure; respect your own overall timeout if you need stricter limits than the built-in 10-minute `wait` budget.

3. **`wait` vs `submit-*`:** **`wait`** is one blocking call; it does **not** emit a separate “submitted” line for the user unless **your** layer prints one before/after. For “notify immediately, then poll in the open,” use **`submit-*`** and your own **`status`** loop with the backoff above.

4. **When generation finishes:** Summarize the **outcome** for the user: on success, **playable links** from **`videos`** (e.g. Markdown `[label](url)`); on failure, **`errorCode`** and **`errorMessage`**. **`video_gen.js` does not know which skill was used**—add **skill attribution** yourself from the active skill’s **`SKILL.md`** (e.g. frontmatter **`name`**) or the skill folder slug, in the same user-facing message.

---

## JSON field reference

| Field | Role |
|--------|------|
| `model` | **Required** (non-empty). No default. |
| `prompt` | **Required** for generation commands. |
| `duration` | Sent as number; default **5** if missing/invalid in script—still must be valid for the model. |
| `aspect_ratio` | Optional; model-dependent. |
| `resolution` | Optional; model-dependent. |
| `generate_audio` | Optional boolean; model-dependent. |
| `negative_prompt` | Optional string; model-dependent. |
| `image` | **Image-to-video:** use a **public `https` image URL** (required for normal use). Local path / `file://` is **script-only**: uploads first, then the API receives the returned public URL. |
| `images` | **Multi-image-to-video:** each entry must end up as a **public `https` URL** (directly, or via the script’s upload step). Up to **3** entries are forwarded after preparation. |

Do not send fields the chosen model does not support (reduces spurious `1002` / parameter errors).

---

## Status & stdout conventions

- HTTP OK with business `status === 0` (or `200` in some responses): request accepted for that layer.
- Generation success: look for completed phase and `videos` with `url` / `cover_url`.
- Errors: stdout JSON with `ok: false`, `errorCode`, `errorMessage` (script maps common API codes to short messages).
- Common keys: `ok`, `phase`, `taskId`, `batchId`, `taskIds`, `videos`, `tasks`, `inProgress`, `errorCode`, `errorMessage`.

---

**Reminder:** Skills may require user confirmation before any paid `wait` / `submit-*` call. For **any** image-to-video flow, assume **public `https` image URLs are mandatory** unless the skill explicitly documents a vetted local-upload path—always follow the active skill’s **`SKILL.md`**.


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)