@acedatacloud/skills 2026.613.0 → 2026.614.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/AGENTS.md CHANGED
@@ -26,6 +26,9 @@ Skills are located in the `skills/` directory (also mirrored to `.agents/skills/
26
26
  - **seedance-video** — Generate dance/motion videos with ByteDance Seedance
27
27
  - **wan-video** — Generate videos with Alibaba Wan
28
28
 
29
+ ### Video Production (workflow)
30
+ - **marketing-video-factory** — Produce a short-form marketing/feature video end-to-end (orchestrates the media skills: generate assets → capture UI → assemble with FFmpeg → distribute)
31
+
29
32
  ### AI Chat & Tools
30
33
  - **ai-chat** — Unified LLM gateway — GPT, Claude, Gemini, Kimi, Grok (50+ models)
31
34
  - **google-search** — Search the web, images, news, maps, places, and videos via Google
package/README.md CHANGED
@@ -42,6 +42,12 @@ Compatible with **30+ AI coding agents** via the [agentskills.io](https://agents
42
42
  | [hailuo-video](skills/hailuo-video/) | Generate videos with Hailuo / MiniMax |
43
43
  | [seedance-video](skills/seedance-video/) | Generate dance/motion videos with ByteDance Seedance |
44
44
 
45
+ ### Video Production (workflow)
46
+
47
+ | Skill | Description |
48
+ |-------|-------------|
49
+ | [marketing-video-factory](skills/marketing-video-factory/) | Produce a short-form marketing/feature video end-to-end — generate assets + capture UI + assemble (FFmpeg) + distribute |
50
+
45
51
  ### AI Chat & Tools
46
52
 
47
53
  | Skill | Description |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acedatacloud/skills",
3
- "version": "2026.613.0",
3
+ "version": "2026.614.0",
4
4
  "description": "Agent Skills for AceDataCloud AI services — music, image, video generation, LLM chat, web search. Compatible with Claude Code, GitHub Copilot, Gemini CLI, OpenAI Codex, and 30+ AI coding agents.",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -0,0 +1,68 @@
1
+ ---
2
+ name: blogger
3
+ description: Publish posts to your Blogger blog and read your blogs / posts via the Blogger API v3. Use when the user mentions Blogger, blogspot, publishing a post to their blog, listing their blogs, or updating an existing Blogger post.
4
+ when_to_use: |
5
+ Trigger when the user wants to publish a post to their Blogger blog,
6
+ list their blogs, list / read posts on a blog, or update an existing
7
+ post. The connector grants the Blogger scope (read + write); confirm
8
+ before publishing publicly (you can insert as a draft first).
9
+ connections: [google/blogger]
10
+ allowed_tools: [Bash]
11
+ license: Apache-2.0
12
+ metadata:
13
+ author: acedatacloud
14
+ version: "1.0"
15
+ ---
16
+
17
+ Call the **Blogger API v3** with `curl + jq`. The user's OAuth bearer token is
18
+ in `$GOOGLE_BLOGGER_TOKEN`; every call needs
19
+ `Authorization: Bearer $GOOGLE_BLOGGER_TOKEN`. Base URL:
20
+ `https://www.googleapis.com/blogger/v3`.
21
+
22
+ Errors are `{"error": {"code": ..., "message": ...}}` — show them verbatim.
23
+ `401` → token expired, re-connect the Blogger connector.
24
+
25
+ **Always start by listing the user's blogs** to get a `blogId`:
26
+
27
+ ```bash
28
+ curl -sS -H "Authorization: Bearer $GOOGLE_BLOGGER_TOKEN" \
29
+ "https://www.googleapis.com/blogger/v3/users/self/blogs" \
30
+ | jq '.items[] | {id, name, url}'
31
+ ```
32
+
33
+ ## Publish a post
34
+
35
+ **Confirm before publishing publicly.** Use `?isDraft=true` to stage a draft.
36
+
37
+ ```bash
38
+ BLOG_ID="1234567890"
39
+ jq -n --arg t "My title" --arg c "<p>HTML content of the post…</p>" \
40
+ '{kind:"blogger#post", title:$t, content:$c, labels:["ai","video"]}' \
41
+ | curl -sS -X POST \
42
+ "https://www.googleapis.com/blogger/v3/blogs/$BLOG_ID/posts/?isDraft=false" \
43
+ -H "Authorization: Bearer $GOOGLE_BLOGGER_TOKEN" \
44
+ -H "Content-Type: application/json" \
45
+ -d @- \
46
+ | jq '{id, url, status}'
47
+ ```
48
+
49
+ `content` is **HTML** (not Markdown) — convert Markdown to HTML first
50
+ (e.g. with `pandoc -f markdown -t html` or a simple converter).
51
+
52
+ - Publish a staged draft: `POST /blogs/{blogId}/posts/{postId}/publish`.
53
+ - Update a post: `PUT /blogs/{blogId}/posts/{postId}` with the same shape.
54
+
55
+ ## List / read posts
56
+
57
+ ```bash
58
+ curl -sS -H "Authorization: Bearer $GOOGLE_BLOGGER_TOKEN" \
59
+ "https://www.googleapis.com/blogger/v3/blogs/$BLOG_ID/posts?maxResults=20&status=live" \
60
+ | jq '.items[] | {id, title, url, published}'
61
+ ```
62
+
63
+ ## Gotchas
64
+
65
+ - **Enable the Blogger API** on the Google Cloud project backing the OAuth
66
+ client, or calls 403 with `accessNotConfigured`.
67
+ - `content` must be HTML; passing raw Markdown will render literally.
68
+ - Paginate with `&pageToken=$PAGE_TOKEN` from the previous `.nextPageToken`.
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: devto
3
+ description: Publish, update and read articles on DEV (dev.to) via the Forem API v1. Use when the user mentions dev.to / DEV Community, publishing a blog post to dev.to, cross-posting an article, updating a published post, or listing their dev.to articles and stats.
4
+ when_to_use: |
5
+ Trigger when the user wants to publish a Markdown article to their
6
+ dev.to account, update a previously published article, or list /
7
+ inspect their own dev.to articles (views, reactions, comments). The
8
+ connector stores a DEV API Key with full account access — confirm
9
+ before publishing publicly (you can publish as a draft with
10
+ published=false first).
11
+ connections: [devto]
12
+ allowed_tools: [Bash]
13
+ license: Apache-2.0
14
+ metadata:
15
+ author: acedatacloud
16
+ version: "1.0"
17
+ ---
18
+
19
+ Call the **Forem API v1** (dev.to) with `curl + jq`. The user's API key is in
20
+ `$DEVTO_API_KEY`; every call needs the headers `api-key: $DEVTO_API_KEY` and
21
+ `Accept: application/vnd.forem.api-v1+json`. Base URL: `https://dev.to/api`.
22
+
23
+ Errors come back as JSON with an `error` / `status` field — show them verbatim.
24
+ `401` means the API key is invalid → the user must re-connect the DEV connector.
25
+
26
+ **Always start by confirming the key** and learning the account:
27
+
28
+ ```bash
29
+ curl -sS -H "api-key: $DEVTO_API_KEY" -H "Accept: application/vnd.forem.api-v1+json" \
30
+ "https://dev.to/api/users/me" | jq '{username, name}'
31
+ ```
32
+
33
+ ## Publish an article
34
+
35
+ **Confirm with the user before publishing publicly.** Default to a draft
36
+ (`published:false`) unless they explicitly say publish/now.
37
+
38
+ ```bash
39
+ TITLE="My title"
40
+ BODY_MD="$(cat article.md)" # full Markdown body
41
+ jq -n --arg t "$TITLE" --arg b "$BODY_MD" \
42
+ '{article:{title:$t, body_markdown:$b, published:false, tags:["ai","webdev"]}}' \
43
+ | curl -sS -X POST "https://dev.to/api/articles" \
44
+ -H "api-key: $DEVTO_API_KEY" \
45
+ -H "Accept: application/vnd.forem.api-v1+json" \
46
+ -H "Content-Type: application/json" \
47
+ -d @- \
48
+ | jq '{id, url, published}'
49
+ ```
50
+
51
+ To publish a draft later (or edit), `PUT /api/articles/{id}` with the same
52
+ shape (set `published:true`). Front-matter inside `body_markdown` (a `---`
53
+ block) can also carry `title`, `tags`, `series`, `canonical_url`, `cover_image`.
54
+
55
+ - **Canonical URL:** when cross-posting, set
56
+ `"canonical_url":"https://your-blog/original"` so DEV points SEO back to the
57
+ source — important for the article→video / cross-publishing flow.
58
+
59
+ ## List / inspect my articles
60
+
61
+ ```bash
62
+ # My published + draft articles (paginated; per_page max 1000).
63
+ curl -sS -H "api-key: $DEVTO_API_KEY" -H "Accept: application/vnd.forem.api-v1+json" \
64
+ "https://dev.to/api/articles/me/all?per_page=30" \
65
+ | jq '.[] | {id, title, published, page_views_count, public_reactions_count, comments_count}'
66
+
67
+ # A single article's full content + stats.
68
+ curl -sS -H "api-key: $DEVTO_API_KEY" -H "Accept: application/vnd.forem.api-v1+json" \
69
+ "https://dev.to/api/articles/ARTICLE_ID" | jq '{title, url, reactions: .public_reactions_count, views: .page_views_count}'
70
+ ```
71
+
72
+ ## Gotchas
73
+
74
+ - **Tags:** max 4, lowercase, no spaces (e.g. `webdev`, `machinelearning`).
75
+ - **Rate limit:** article create/update is throttled (a few per 30s); space out
76
+ bulk publishes or you'll get `429`.
77
+ - `body_markdown` is the source of truth — if you put a `---` front-matter block
78
+ at the top, its fields override the JSON `article` fields.
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: linkedin
3
+ description: Publish text / link posts to your LinkedIn personal feed via the LinkedIn Posts API. Use when the user mentions LinkedIn, sharing or posting an update to LinkedIn, or cross-posting an article / link to their LinkedIn feed.
4
+ when_to_use: |
5
+ Trigger when the user wants to publish a text or link share to their
6
+ own LinkedIn feed. Posting is public on their profile — confirm the
7
+ text (and link, if any) before publishing. Requires the
8
+ w_member_social scope (granted by the connector at install).
9
+ connections: [linkedin]
10
+ allowed_tools: [Bash]
11
+ license: Apache-2.0
12
+ metadata:
13
+ author: acedatacloud
14
+ version: "1.0"
15
+ ---
16
+
17
+ Call the **LinkedIn API** with `curl + jq`. The user's bearer token is in
18
+ `$LINKEDIN_TOKEN`; every call needs `Authorization: Bearer $LINKEDIN_TOKEN`.
19
+
20
+ LinkedIn posts must be authored by the member's URN. Get the member id from the
21
+ OpenID userinfo endpoint, then build `urn:li:person:{sub}`.
22
+
23
+ ```bash
24
+ SUB=$(curl -sS -H "Authorization: Bearer $LINKEDIN_TOKEN" \
25
+ "https://api.linkedin.com/v2/userinfo" | jq -r .sub)
26
+ AUTHOR="urn:li:person:$SUB"
27
+ echo "$AUTHOR"
28
+ ```
29
+
30
+ Errors are JSON with `message` / `serviceErrorCode` — show them verbatim.
31
+ `401` → token expired (tokens last ~60 days), re-connect the LinkedIn connector.
32
+
33
+ ## Publish a post (Posts API)
34
+
35
+ **Confirm the text with the user first.** Use the versioned Posts API; set the
36
+ `LinkedIn-Version` header to a recent `YYYYMM` (LinkedIn requires a valid recent
37
+ version — if you get `426`/version errors, bump to the current month).
38
+
39
+ ```bash
40
+ jq -n --arg a "$AUTHOR" --arg t "My update text. Check out https://studio.acedata.cloud" \
41
+ '{author:$a, commentary:$t, visibility:"PUBLIC",
42
+ distribution:{feedDistribution:"MAIN_FEED", targetEntities:[], thirdPartyDistributionChannels:[]},
43
+ lifecycleState:"PUBLISHED", isReshareDisabledByAuthor:false}' \
44
+ | curl -sS -X POST "https://api.linkedin.com/rest/posts" \
45
+ -H "Authorization: Bearer $LINKEDIN_TOKEN" \
46
+ -H "Content-Type: application/json" \
47
+ -H "LinkedIn-Version: 202401" \
48
+ -H "X-Restli-Protocol-Version: 2.0.0" \
49
+ -d @- -D - -o /dev/null | tr -d '\r' | awk '/^[Xx]-[Rr]estli-[Ii]d:|^[Ll]ocation:/{print}'
50
+ ```
51
+
52
+ A successful create returns `201` with the post URN in the `x-restli-id`
53
+ (or `Location`) response header — report that URN / the resulting post URL.
54
+
55
+ > Link posts: put the URL inline in `commentary` (LinkedIn auto-unfurls it).
56
+ > Rich article attachments need the assets/images API — out of scope for a
57
+ > simple text/link share; keep links inline.
58
+
59
+ ## Fallback: legacy ugcPosts
60
+
61
+ If the versioned endpoint is unavailable for the app, the older
62
+ `POST https://api.linkedin.com/v2/ugcPosts` with a
63
+ `specificContent."com.linkedin.ugc.ShareContent"` body also works with
64
+ `w_member_social`. Prefer `/rest/posts` above.
65
+
66
+ ## Gotchas
67
+
68
+ - **Author URN** must match the token's member (`urn:li:person:{sub}`) — you
69
+ can't post as someone else.
70
+ - `w_member_social` only allows posting to the **member's own feed**; company
71
+ Page posts need `w_organization_social` + an admin role (not in this connector).
72
+ - The `LinkedIn-Version` header is mandatory for `/rest/*`; a stale value
73
+ returns a version error — bump to the current `YYYYMM`.
@@ -0,0 +1,172 @@
1
+ ---
2
+ name: marketing-video-factory
3
+ description: Produce a short-form (9:16, ~30-60s) marketing / feature-explainer video end-to-end using AceDataCloud's own AI APIs — generate B-roll + hero images (Flux/Seedream/NanoBanana/Seedance), a music bed (Suno) and voiceover (TTS), capture real product UI with Playwright, assemble with FFmpeg (burned-in captions), upload to CDN, then distribute. Use when the user wants to make a promo/feature/explainer video, a TikTok/Reels/Shorts/Bilibili/Douyin short, "automated video marketing", or to turn a product feature into a vertical video.
4
+ when_to_use: |
5
+ Trigger when the user wants to PRODUCE a finished short-form video
6
+ (not just call one model): a marketing/feature/promo/explainer short,
7
+ a vertical video for TikTok / YouTube Shorts / Reels / Bilibili /
8
+ Douyin / X / LinkedIn, or an "automated video factory". This skill is
9
+ the playbook that orchestrates the single-service skills
10
+ (flux-image, seedream-image, nano-banana-image, seedance-video,
11
+ veo-video, suno-music, fish-audio, short-url) into one pipeline.
12
+ allowed_tools: [Bash]
13
+ license: Apache-2.0
14
+ metadata:
15
+ author: acedatacloud
16
+ version: "1.0"
17
+ compatibility: Requires ACEDATACLOUD_API_TOKEN (model calls) and ACEDATACLOUD_PLATFORM_TOKEN (CDN upload) in .env (see _shared/authentication.md). Needs ffmpeg, python3 + pillow, and (for screenshots) playwright. Optionally pair with the per-service MCP servers (_shared/mcp-servers.md).
18
+ ---
19
+
20
+ # Marketing Video Factory
21
+
22
+ Turn a product feature into a platform-ready vertical short, made **with the same
23
+ AI APIs you're advertising** (so the video is also a live demo of itself).
24
+
25
+ > **Setup:** [authentication](../_shared/authentication.md) · async behavior:
26
+ > [async task polling](../_shared/async-tasks.md) · tool-use: [MCP servers](../_shared/mcp-servers.md).
27
+
28
+ ## Strategy (read first)
29
+
30
+ 1. **Dogfood.** Generate every asset through `api.acedata.cloud` (Flux, Seedream,
31
+ NanoBanana, Seedance/Veo, Suno, TTS). The output *is* the proof.
32
+ 2. **Real UI is the spine; AI footage is the spice.** For a software/dev product,
33
+ show real screen-captures/screenshots of the product for the demo beats;
34
+ reserve AI-generated clips for intro / atmosphere / transitions. AI models
35
+ hallucinate fake buttons/code → never use them to depict the actual product.
36
+ 3. **Structure every video:** `Hook (0-3s) → Value (4-15s) → Demo (16-50s) →
37
+ CTA (last ~5s)`. One cut every 2-4s. Captions always on (≈85% watch muted).
38
+
39
+ ## Workflow
40
+
41
+ 1. **Brief** the feature: pull real value-prop copy from your docs (verbatim
42
+ on-screen text beats invented copy).
43
+ 2. **Script** a Scene-JSON: per scene = `{visual, duration, caption}`, following
44
+ the hook→value→demo→CTA skeleton.
45
+ 3. **Generate assets** (async — submit then poll): hero/B-roll images, B-roll
46
+ clips, a music bed, voiceover. Use `watermark=false`. Pin aspect to 9:16.
47
+ 4. **Capture UI** screenshots with Playwright (mobile 9:16 viewport).
48
+ 5. **Assemble** with FFmpeg: per-scene render → concat → mix music. Burn captions.
49
+ 6. **Upload** the final MP4 to the CDN; **distribute** per platform.
50
+
51
+ ## Recipe — generate an asset (submit + poll)
52
+
53
+ ```bash
54
+ # Hero / B-roll image. Flux & NanoBanana honor true 9:16; Seedream size is an
55
+ # ENUM (1K/2K/...) and tends to return 16:9 — use Flux for vertical heroes.
56
+ curl -sS -X POST https://api.acedata.cloud/flux/images \
57
+ -H "Authorization: Bearer $ACEDATACLOUD_API_TOKEN" -H "Content-Type: application/json" \
58
+ -d '{"model":"flux-2-pro","prompt":"<scene visual>, deep violet/indigo, cinematic, no text","size":"9:16"}'
59
+
60
+ # B-roll clip (Seedance is fast/cheap; Veo for hero quality). watermark off.
61
+ curl -sS -X POST https://api.acedata.cloud/seedance/videos \
62
+ -H "Authorization: Bearer $ACEDATACLOUD_API_TOKEN" -H "Content-Type: application/json" \
63
+ -d '{"model":"doubao-seedance-2-0-fast-260128","content":[{"type":"text","text":"<motion>, 9:16, no text"}],"resolution":"720p","ratio":"9:16","duration":5,"watermark":false}'
64
+
65
+ # Music bed — instrumental (see suno-music). Then poll /suno/tasks.
66
+ curl -sS -X POST https://api.acedata.cloud/suno/audios \
67
+ -H "Authorization: Bearer $ACEDATACLOUD_API_TOKEN" -H "Content-Type: application/json" \
68
+ -d '{"action":"generate","prompt":"uplifting minimal electronic, premium tech","instrumental":true,"model":"chirp-v5-5"}'
69
+ ```
70
+
71
+ All of the above return a `task_id` — **poll the matching `/<service>/tasks`** until
72
+ `state`/`status` is terminal, then read the media URL (see _shared/async-tasks.md).
73
+ The media is served from `*.cdn.acedata.cloud`. Per-model details: `flux-image`,
74
+ `seedream-image`, `nano-banana-image`, `seedance-video`, `veo-video`, `suno-music`,
75
+ `fish-audio` skills. (Voiceover: `POST /text-to-speech`, keep word timings for
76
+ karaoke captions.)
77
+
78
+ ## Recipe — capture product UI (Playwright)
79
+
80
+ ```python
81
+ # pip install playwright && python -m playwright install chromium
82
+ from playwright.sync_api import sync_playwright
83
+ with sync_playwright() as p:
84
+ b = p.chromium.launch(headless=True)
85
+ # 9:16 viewport so a vertical video doesn't center-crop a desktop layout.
86
+ ctx = b.new_context(viewport={"width":1080,"height":1920}, device_scale_factor=2,
87
+ storage_state="auth.json") # omit for public pages
88
+ pg = ctx.new_page(); pg.goto(URL, wait_until="networkidle"); pg.wait_for_timeout(3500)
89
+ pg.screenshot(path="shot.png")
90
+ ```
91
+
92
+ **Public marketing pages capture anonymously; logged-in console/app pages need a
93
+ saved `storage_state`** (a throwaway demo account) — without it they redirect to
94
+ the login wall.
95
+
96
+ ## Recipe — assemble (per-scene render → concat → music)
97
+
98
+ Do **NOT** build one giant filtergraph with all inputs — with several hi-res
99
+ images + caption PNGs it OOMs ("Cannot allocate memory"). Render each scene
100
+ to an intermediate, then concat (stream-copy), then mux music:
101
+
102
+ ```bash
103
+ W=1080; H=1920; FPS=30
104
+ SCALE="scale=$W:$H:force_original_aspect_ratio=increase,crop=$W:$H,setsar=1,fps=$FPS"
105
+
106
+ # Per scene: a still (loop to DUR) or a clip (trim to DUR) + a transparent
107
+ # caption PNG overlaid. Produce identical-codec segNN.mp4 (no audio).
108
+ ffmpeg -y -loop 1 -t $DUR -i still.png -loop 1 -i capNN.png \
109
+ -filter_complex "[0:v]$SCALE[bg];[bg][1:v]overlay=0:0:shortest=1[v]" \
110
+ -map "[v]" -an -t $DUR -c:v libx264 -pix_fmt yuv420p -r $FPS \
111
+ -video_track_timescale 15360 segNN.mp4
112
+ # (for a clip scene: replace "-loop 1 -t $DUR -i still.png" with "-i clip.mp4")
113
+
114
+ # Concat (all segments share codec/params) + mix music under, with a fade-out.
115
+ printf "file 'seg00.mp4'\nfile 'seg01.mp4'\n..." > segs.txt
116
+ ffmpeg -y -f concat -safe 0 -i segs.txt -c copy video_silent.mp4
117
+ ffmpeg -y -i video_silent.mp4 -i music.mp3 \
118
+ -filter_complex "[1:a]volume=-3dB,afade=t=out:st=$(($TOTAL-1)):d=1[a]" \
119
+ -map 0:v -map "[a]" -c:v copy -c:a aac -shortest one-api-key.mp4
120
+ ```
121
+
122
+ Captions: render each as a **transparent PNG** (Pillow) and overlay — portable
123
+ across all ffmpeg builds (avoids the libfreetype `drawtext` dependency). Use a
124
+ real bold sans (`C:/Windows/Fonts/arialbd.ttf`, `DejaVuSans-Bold.ttf`, etc.),
125
+ 3-7 words/line, white + black stroke; push to the **upper third during UI demos**
126
+ so the product stays visible.
127
+
128
+ > Reference implementation (Scene-JSON contract, caption-burn, render driver,
129
+ > material-library convention): **AceDataCloud/PlatformStudio** (`app/`,
130
+ > `scripts/build_video.py`, `assets/MATERIALS.md`).
131
+
132
+ ## Recipe — upload to CDN + distribute
133
+
134
+ ```bash
135
+ curl -sS -X POST https://platform.acedata.cloud/api/v1/files/ \
136
+ -H "Authorization: Bearer $ACEDATACLOUD_PLATFORM_TOKEN" \
137
+ -F "file=@one-api-key.mp4" # -> {"file_url":"https://cdn.acedata.cloud/....mp4"}
138
+ ```
139
+
140
+ Distribute with a short link (`short-url` skill) + per-platform metadata. Author
141
+ once at 1080×1920 inside a centered 900×1400 safe box, then atomize to 16:9 / 1:1.
142
+
143
+ ## Creative cheat-sheet
144
+
145
+ - **Length:** TikTok 15-34s · Shorts/Reels 30-60s · X <60s · LinkedIn 30-90s.
146
+ - **Captions:** always on, karaoke word-highlight, avoid bottom ~20-25% & right edge.
147
+ - **Audio:** final mix ≈ **−14 LUFS**, music **15-20 dB under** voice; sidechain-duck
148
+ (`sidechaincompress`) the music off the narration; `loudnorm=I=-14:TP=-1:LRA=11`.
149
+ - **CTA:** one clear visual CTA in the last ~5s (assume muted).
150
+
151
+ ## Gotchas
152
+
153
+ - **Generation is async** — every model call returns a `task_id`; poll the
154
+ service's `/tasks` endpoint. Don't treat the first response as the result.
155
+ - **Aspect:** pin 9:16 explicitly. `seedream` `size` is an enum (1K/2K/3K/4K) and
156
+ skews 16:9 → use **Flux** (`size:"9:16"`) or **NanoBanana** (`aspect_ratio`) for
157
+ true vertical heroes.
158
+ - **`watermark:false`** on marketing assets (Seedance/Seedream default to true).
159
+ - **Single mega-filtergraph OOMs** on multi-input hi-res jobs → render per-scene
160
+ then `concat -c copy` (above).
161
+ - **Screenshots:** use a **9:16 viewport** (not a desktop one center-cropped);
162
+ logged-in pages need a saved Playwright `storage_state`.
163
+ - **CDN download SSL:** some hosts (e.g. `cdn1.suno.ai`) fail Python `urllib`
164
+ cert verification → fetch with `curl -L` instead.
165
+ - **Music licensing:** Suno free tier is **non-commercial**; paid plans give no
166
+ indemnification → for **paid ads** use a fully-licensed library; keep Suno for
167
+ organic. Master to −14 LUFS regardless.
168
+ - **Don't hard-couple the video model** — keep it swappable (Veo/Seedance/Luma);
169
+ abstract the provider so a deprecation (e.g. a Sora API sunset) is a 1-line change.
170
+ - **Cross-posting:** strip watermarks before re-uploading; rewrite title/hashtags
171
+ per platform; keep Instagram reposts <10 / 30 days; use a humane cadence (bursts
172
+ read as spam).
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: reddit
3
+ description: Submit posts (link or text) to subreddits and read your Reddit identity / content via the Reddit API. Use when the user mentions Reddit, posting to a subreddit, submitting a link or self-post, or checking their Reddit profile / submissions.
4
+ when_to_use: |
5
+ Trigger when the user wants to submit a post to a subreddit (link or
6
+ self/text post), or read their own Reddit identity and submissions.
7
+ Posting to a subreddit is public and subject to that subreddit's rules
8
+ / karma requirements — confirm the target subreddit, title and body
9
+ before submitting.
10
+ connections: [reddit]
11
+ allowed_tools: [Bash]
12
+ license: Apache-2.0
13
+ metadata:
14
+ author: acedatacloud
15
+ version: "1.0"
16
+ ---
17
+
18
+ Call the **Reddit API** (OAuth endpoints) with `curl + jq`. The user's bearer
19
+ token is in `$REDDIT_TOKEN`. **Every call MUST send a `User-Agent` header** or
20
+ Reddit returns `429`. Use the OAuth host `https://oauth.reddit.com`.
21
+
22
+ ```bash
23
+ UA="web:cloud.acedata.connectors:v1.0 (by /u/acedatacloud)"
24
+ ```
25
+
26
+ Errors are JSON; a submit returns `{"json":{"errors":[...], "data":{...}}}` —
27
+ if `errors` is non-empty, show them verbatim. `401` → token expired, re-connect.
28
+
29
+ **Always start by confirming identity:**
30
+
31
+ ```bash
32
+ curl -sS -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
33
+ "https://oauth.reddit.com/api/v1/me" | jq '{name, total_karma, link_karma}'
34
+ ```
35
+
36
+ ## Submit a post
37
+
38
+ **Confirm the subreddit + title + body with the user first.** `sr` is the
39
+ subreddit name WITHOUT the `r/` prefix.
40
+
41
+ ```bash
42
+ # Self (text) post: kind=self + text. Link post: kind=link + url.
43
+ curl -sS -X POST "https://oauth.reddit.com/api/submit" \
44
+ -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
45
+ --data-urlencode "sr=test" \
46
+ --data-urlencode "kind=self" \
47
+ --data-urlencode "title=My title" \
48
+ --data-urlencode "text=My self-post body in markdown" \
49
+ --data-urlencode "api_type=json" \
50
+ | jq '.json | {errors, url: .data.url, id: .data.id}'
51
+ ```
52
+
53
+ For a link post:
54
+
55
+ ```bash
56
+ curl -sS -X POST "https://oauth.reddit.com/api/submit" \
57
+ -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
58
+ --data-urlencode "sr=test" --data-urlencode "kind=link" \
59
+ --data-urlencode "title=My title" --data-urlencode "url=https://example.com" \
60
+ --data-urlencode "api_type=json" | jq '.json'
61
+ ```
62
+
63
+ ## Read my submissions
64
+
65
+ ```bash
66
+ curl -sS -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
67
+ "https://oauth.reddit.com/user/USERNAME/submitted?limit=10" \
68
+ | jq '.data.children[] | .data | {title, subreddit, ups, num_comments, permalink}'
69
+ ```
70
+
71
+ ## Gotchas
72
+
73
+ - **User-Agent is mandatory** on every request — omitting it → `429`.
74
+ - Many subreddits gate posting on **account age / karma / flair**; a submit can
75
+ return `errors` like `[["SUBREDDIT_NOTALLOWED", ...]]` — surface it and try
76
+ `r/test` to validate the flow.
77
+ - Respect rate limits: read the `X-Ratelimit-Remaining` response header; space
78
+ out bulk submits.
79
+ - Use `r/test` as a safe target when validating that the connection works.