@acedatacloud/skills 2026.801.1 → 2026.801.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acedatacloud/skills",
3
- "version": "2026.801.1",
3
+ "version": "2026.801.3",
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",
@@ -1,19 +1,18 @@
1
1
  ---
2
2
  name: tiktok
3
- description: Post videos to the user's TikTok — either published directly (with caption and privacy the user chooses) or uploaded to their drafts/inbox — and read their TikTok profile, stats and video list. Use when the user wants to publish or post a generated video to TikTok, send a video to their TikTok drafts, or check their TikTok account and performance.
3
+ description: Upload videos to the user's TikTok drafts/inbox, where they finish posting in the TikTok app. Use when the user wants to publish or post a generated video to TikTok, or send a video to their TikTok drafts.
4
4
  when_to_use: |
5
5
  Trigger when the user wants to push a video (e.g. one generated by
6
- the video skills) to TikTok, or to read their TikTok account and
7
- post performance. Direct Post publishes immediately with a caption
8
- and a privacy level the user picks; Upload drops it into drafts for
9
- them to finish in the app. Always confirm caption and privacy with
10
- the user before posting — never post unattended.
6
+ the video skills) to TikTok. Upload drops it into their drafts and
7
+ they finish posting in the app — this is the working path. Direct
8
+ Post (publishing immediately with caption + privacy) requires an
9
+ audit this app has not passed yet; do not use it.
11
10
  connections: [tiktok]
12
11
  allowed_tools: [Bash]
13
12
  license: Apache-2.0
14
13
  metadata:
15
14
  author: acedatacloud
16
- version: "2.0"
15
+ version: "2.2"
17
16
  ---
18
17
 
19
18
  Call the **TikTok API v2** with `curl + jq`. The user's OAuth bearer token is in
@@ -33,84 +32,52 @@ Responses wrap everything in `{"data":…,"error":{"code","message","log_id"}}`.
33
32
  ## Read the account
34
33
 
35
34
  ```bash
36
- # Profile + stats (needs user.info.profile / user.info.stats)
37
- curl -sS -H "$AUTH" "$T/user/info/?fields=open_id,display_name,avatar_url,username,is_verified,follower_count,following_count,likes_count,video_count" \
35
+ # Basic profile — open_id identifies the user for every posting call
36
+ curl -sS -H "$AUTH" "$T/user/info/?fields=open_id,display_name,avatar_url" \
38
37
  | jq '.data.user'
39
38
  ```
40
39
 
41
- ## List the user's videos
40
+ Follower / like counts, bio, and the user's video list need the **Display API**
41
+ scopes (`user.info.stats`, `user.info.profile`, `video.list`), which this app
42
+ has not been granted — don't call `/v2/video/list/` or request those fields,
43
+ they will fail with `scope_not_authorized`.
42
44
 
43
- `fields` goes in the **query string**, pagination in the **body** (easy to get
44
- wrong). `max_count` max is 20; `cursor` is a **millisecond** UTC timestamp,
45
- while each video's `create_time` is in **seconds**.
45
+ ## Upload the video to the user's drafts
46
46
 
47
- ```bash
48
- curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
49
- "$T/video/list/?fields=id,title,video_description,create_time,duration,cover_image_url,share_url,view_count,like_count,comment_count,share_count" \
50
- -d '{"max_count":20}' | jq '{videos:.data.videos, cursor:.data.cursor, has_more:.data.has_more}'
51
- ```
52
-
53
- Only **public** videos are returned, newest first.
54
-
55
- ## Direct Post — publish straight to the account
56
-
57
- Three steps, in this order. **Step 1 is mandatory** and its result drives what
58
- you may offer the user.
59
-
60
- ### 1. Query creator info (required before every post)
61
-
62
- ```bash
63
- curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
64
- "$T/post/publish/creator_info/query/" | jq '.data, .error.code'
65
- ```
66
-
67
- Returns `creator_nickname`, `privacy_level_options`, `comment_disabled`,
68
- `duet_disabled`, `stitch_disabled`, `max_video_post_duration_sec`.
69
-
70
- Use it to:
71
- - **Show the user `creator_nickname`** so they know which account will receive
72
- the post.
73
- - **Offer only the returned `privacy_level_options`** — a public account gets
74
- `PUBLIC_TO_EVERYONE` / `MUTUAL_FOLLOW_FRIENDS` / `SELF_ONLY`; a private one
75
- gets `FOLLOWER_OF_CREATOR` / `MUTUAL_FOLLOW_FRIENDS` / `SELF_ONLY`.
76
- - **Reject a too-long video** against `max_video_post_duration_sec`.
77
- - Not offer comment/duet/stitch toggles that come back disabled.
78
- - If it returns a spam/cap error, **stop** and tell the user to try later.
47
+ This is the working path. The video lands in the creator's TikTok **inbox /
48
+ drafts**; they open the TikTok app to add caption, sound and privacy, then post.
49
+ Confirm with the user before uploading.
79
50
 
80
- ### 2. Ask the user to confirm
51
+ Two source modes. **`FILE_UPLOAD` is the reliable one** — `PULL_FROM_URL` only
52
+ works from a domain verified in the developer portal, and ours is not verified
53
+ yet (it returns `url_ownership_unverified`).
81
54
 
82
- Before initializing, the user must explicitly confirm — this is a TikTok
83
- requirement, not just good manners:
55
+ ### FILE_UPLOAD (default)
84
56
 
85
- - the **caption** (max 2200 UTF-16 chars; `#tag` and `@mention` work),
86
- - the **privacy level**, **chosen by them from the options above — never
87
- default to one, never assume `PUBLIC_TO_EVERYONE`**,
88
- - and tell them: *"By posting, you agree to TikTok's Music Usage Confirmation."*
89
-
90
- ### 3. Initialize the post
57
+ Download the video locally first, then init with its exact byte size. Files
58
+ under 64 MB go up as a single chunk.
91
59
 
92
60
  ```bash
93
- VIDEO_URL="https://cdn.acedata.cloud/….mp4" # verified-domain public URL
94
- curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
95
- -d "$(jq -n --arg t "$CAPTION" --arg p "$PRIVACY" --arg u "$VIDEO_URL" '{
96
- post_info: {title:$t, privacy_level:$p, is_aigc:true},
97
- source_info: {source:"PULL_FROM_URL", video_url:$u}}')" \
98
- "$T/post/publish/video/init/" | jq '{publish_id:.data.publish_id, error}'
61
+ SIZE=$(stat -f%z video.mp4 2>/dev/null || stat -c%s video.mp4)
62
+
63
+ INIT=$(curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
64
+ -d "$(jq -n --argjson s "$SIZE" \
65
+ '{source_info:{source:"FILE_UPLOAD", video_size:$s, chunk_size:$s, total_chunk_count:1}}')" \
66
+ "$T/post/publish/inbox/video/init/")
67
+ echo "$INIT" | jq '{publish_id:.data.publish_id, error:.error.code}'
68
+
69
+ UPLOAD_URL=$(echo "$INIT" | jq -r '.data.upload_url')
70
+ curl -sS -X PUT "$UPLOAD_URL" \
71
+ -H "Content-Type: video/mp4" \
72
+ -H "Content-Length: $SIZE" \
73
+ -H "Content-Range: bytes 0-$((SIZE-1))/$SIZE" \
74
+ --data-binary @video.mp4 -o /dev/null -w '%{http_code}\n'
99
75
  ```
100
76
 
101
- **Set `is_aigc: true` whenever the video was AI-generated** (anything from our
102
- video skills). TikTok labels it "Creator labeled as AI-generated" — required
103
- disclosure, and omitting it risks the post being taken down.
104
-
105
- Optional `post_info` fields: `disable_comment`, `disable_duet`,
106
- `disable_stitch`, `video_cover_timestamp_ms`. If the user says the video is a
107
- paid partnership, set `brand_content_toggle: true` (which cannot be combined
108
- with `SELF_ONLY`); for promoting their own business use `brand_organic_toggle`.
109
-
110
- ## Upload to drafts instead
77
+ The `PUT` returns **201** when the whole file landed (206 for intermediate
78
+ chunks). `upload_url` expires in **1 hour**.
111
79
 
112
- When the user would rather finish in the app, use the inbox endpoint — no
113
- caption or privacy, and **no `creator_info` call needed**:
80
+ ### PULL_FROM_URL (only from a verified domain)
114
81
 
115
82
  ```bash
116
83
  curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
@@ -118,35 +85,49 @@ curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
118
85
  "$T/post/publish/inbox/video/init/" | jq '{publish_id:.data.publish_id, error}'
119
86
  ```
120
87
 
121
- ## Poll status (both flows)
88
+ Needs HTTPS and **no redirects** (any 3xx fails). Domain verification covers
89
+ subdomains downward only.
90
+
91
+ ## Poll status
122
92
 
123
93
  ```bash
124
94
  curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
125
95
  -d "$(jq -n --arg id "$PUBLISH_ID" '{publish_id:$id}')" \
126
- "$T/post/publish/status/fetch/" | jq '.data | {status, fail_reason, publicaly_available_post_id}'
96
+ "$T/post/publish/status/fetch/" | jq '.data | {status, fail_reason}'
127
97
  ```
128
98
 
129
- Status: `PROCESSING_DOWNLOAD` / `PROCESSING_UPLOAD` → `SEND_TO_USER_INBOX`
130
- (drafts flow) or `PUBLISH_COMPLETE` (direct post), or `FAILED` with
131
- `fail_reason`. Tell the user processing takes a few minutes.
99
+ `PROCESSING_UPLOAD` / `PROCESSING_DOWNLOAD` → **`SEND_TO_USER_INBOX`** = done,
100
+ the video is waiting in the creator's TikTok inbox. Tell them to open the
101
+ TikTok app to finish posting, and that processing takes a few minutes.
132
102
 
133
103
  Don't retry on `auth_removed`, `spam_risk_text`, `spam_risk`, or
134
104
  `spam_risk_user_banned_from_posting` — those are terminal. `internal` is
135
105
  retryable.
136
106
 
107
+ ## Direct Post — NOT available yet
108
+
109
+ Direct Post (`/v2/post/publish/video/init/`) publishes straight to the profile
110
+ with a caption and privacy level. **Do not call it.** It needs a Content
111
+ Posting API audit this app has not passed, so every attempt fails:
112
+
113
+ ```
114
+ 403 unaudited_client_can_only_post_to_private_accounts
115
+ ```
116
+
117
+ The `video.publish` scope is granted and `creator_info/query` works, which
118
+ makes it look available — it is not. Until the audit clears, use the drafts
119
+ path above.
120
+
137
121
  ## Gotchas
138
122
 
139
- - **Never hardcode `privacy_level`.** TikTok rejects values outside
140
- `privacy_level_options` (`privacy_level_option_mismatch`) and treats a
141
- defaulted privacy setting as a guideline violation for the whole app.
142
- - `publicaly_available_post_id` (TikTok's own spelling — don't "fix" it) is a
143
- **list**, and is **empty for non-public posts and for public posts still in
144
- moderation**. Empty ≠ failure.
145
- - `PULL_FROM_URL` needs the URL's domain verified in the developer app, HTTPS,
146
- and **no redirects** (any 3xx fails). Verification covers subdomains
147
- downward only. If the video isn't on a verified domain, use chunked
148
- `FILE_UPLOAD` (init with `video_size`/`chunk_size`/`total_chunk_count`, then
149
- `PUT` byte ranges to `upload_url`, which expires in 1 hour).
123
+ - **Never hardcode `privacy_level`** if Direct Post is ever enabled. TikTok
124
+ rejects values outside `privacy_level_options` and treats a defaulted privacy
125
+ setting as a guideline violation for the whole app.
150
126
  - Rate limits per user token: `creator_info/query` 20/min, `video/init/`
151
127
  **6/min**, `status/fetch/` 30/min. TikTok also caps posts at roughly 15/day
152
- per creator, shared across all apps.
128
+ per creator, **shared across all apps** — another app can exhaust it.
129
+ - `SEND_TO_USER_INBOX` is success for this flow, not an intermediate state.
130
+ Don't wait for `PUBLISH_COMPLETE` — that only happens once the user posts
131
+ from the app.
132
+
133
+