@acedatacloud/skills 2026.704.2 → 2026.704.4
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 +1 -1
- package/skills/_shared/artifacts.md +28 -0
- package/skills/bilibili/SKILL.md +14 -0
- package/skills/blogger/SKILL.md +14 -0
- package/skills/bluesky/SKILL.md +14 -0
- package/skills/csdn/SKILL.md +14 -0
- package/skills/devto/SKILL.md +14 -0
- package/skills/hashnode/SKILL.md +14 -0
- package/skills/instagram/SKILL.md +120 -0
- package/skills/juejin/SKILL.md +14 -0
- package/skills/linkedin/SKILL.md +14 -0
- package/skills/mastodon/SKILL.md +14 -0
- package/skills/medium/SKILL.md +14 -0
- package/skills/notion/SKILL.md +14 -0
- package/skills/reddit/SKILL.md +14 -0
- package/skills/substack/SKILL.md +14 -0
- package/skills/telegram/SKILL.md +14 -0
- package/skills/threads/SKILL.md +116 -0
- package/skills/wordpress/SKILL.md +14 -0
- package/skills/x/SKILL.md +14 -0
- package/skills/zhihu/SKILL.md +14 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acedatacloud/skills",
|
|
3
|
-
"version": "2026.704.
|
|
3
|
+
"version": "2026.704.4",
|
|
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,28 @@
|
|
|
1
|
+
# Recording produced outputs (`publish_artifact`)
|
|
2
|
+
|
|
3
|
+
Write/publish-capable Skills should record their concrete deliverable so the
|
|
4
|
+
user can later find and aggregate everything the agent produced (in the "My
|
|
5
|
+
Outputs" view at `/chatgpt/artifacts`).
|
|
6
|
+
|
|
7
|
+
After a publish/send/generate action **succeeds and you have the live result
|
|
8
|
+
URL**, call the built-in `publish_artifact` tool exactly ONCE for that
|
|
9
|
+
deliverable:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
publish_artifact(
|
|
13
|
+
kind="article", # article | image | video | audio | document | email | message | dataset | link | other
|
|
14
|
+
channel="<platform>", # e.g. zhihu, csdn, medium, x, mastodon
|
|
15
|
+
title="<human title>",
|
|
16
|
+
url="<the REAL returned URL>",
|
|
17
|
+
status="delivered" # delivered | draft | failed
|
|
18
|
+
)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Rules:
|
|
22
|
+
|
|
23
|
+
- Use the **real URL returned by the publish step** — never fabricate a URL.
|
|
24
|
+
- Call it once per distinct deliverable, right after delivery is confirmed.
|
|
25
|
+
- Do NOT call it for intermediate steps, drafts you didn't submit, or narration.
|
|
26
|
+
- If publishing failed, either skip it or record `status="failed"`.
|
|
27
|
+
|
|
28
|
+
The tool is non-interactive and works in unattended (scheduled-task) runs.
|
package/skills/bilibili/SKILL.md
CHANGED
|
@@ -106,3 +106,17 @@ skips this.
|
|
|
106
106
|
common `tid` values.
|
|
107
107
|
- **Never print `BILIBILI_COOKIES`** — it is full account access.
|
|
108
108
|
- **ToS**: acts only on the user's own account with their own captured cookie.
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
## Record the output
|
|
112
|
+
|
|
113
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
114
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
publish_artifact(kind="article", channel="bilibili", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
121
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
122
|
+
See `_shared/artifacts.md`.
|
package/skills/blogger/SKILL.md
CHANGED
|
@@ -78,3 +78,17 @@ curl -sS -H "Authorization: Bearer $GOOGLE_BLOGGER_TOKEN" \
|
|
|
78
78
|
or reconnect with the account that has the blog.
|
|
79
79
|
- `content` must be HTML; passing raw Markdown will render literally.
|
|
80
80
|
- Paginate with `&pageToken=$PAGE_TOKEN` from the previous `.nextPageToken`.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
## Record the output
|
|
84
|
+
|
|
85
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
86
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
publish_artifact(kind="article", channel="blogger", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
93
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
94
|
+
See `_shared/artifacts.md`.
|
package/skills/bluesky/SKILL.md
CHANGED
|
@@ -112,3 +112,17 @@ extracts the `rkey`. An empty result / `deleted:true` is success.
|
|
|
112
112
|
there; all XRPC calls target that host, not `bsky.social`.
|
|
113
113
|
- The CLI creates a fresh short-lived session on **every** invocation, so an
|
|
114
114
|
expiring `accessJwt` is never a concern — just run the command again.
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
## Record the output
|
|
118
|
+
|
|
119
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
120
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
publish_artifact(kind="message", channel="bluesky", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
127
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
128
|
+
See `_shared/artifacts.md`.
|
package/skills/csdn/SKILL.md
CHANGED
|
@@ -91,3 +91,17 @@ image that fails to upload keeps its original URL (never blocks the post).
|
|
|
91
91
|
- **Never print `CSDN_COOKIES`** — it is full account access.
|
|
92
92
|
- **ToS**: cookie automation acts only on the user's own account with their own
|
|
93
93
|
captured cookie; the user owns that risk.
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
## Record the output
|
|
97
|
+
|
|
98
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
99
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
publish_artifact(kind="article", channel="csdn", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
106
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
107
|
+
See `_shared/artifacts.md`.
|
package/skills/devto/SKILL.md
CHANGED
|
@@ -76,3 +76,17 @@ curl -sS -H "api-key: $DEVTO_API_KEY" -H "Accept: application/vnd.forem.api-v1+j
|
|
|
76
76
|
bulk publishes or you'll get `429`.
|
|
77
77
|
- `body_markdown` is the source of truth — if you put a `---` front-matter block
|
|
78
78
|
at the top, its fields override the JSON `article` fields.
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## Record the output
|
|
82
|
+
|
|
83
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
84
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
publish_artifact(kind="article", channel="devto", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
91
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
92
|
+
See `_shared/artifacts.md`.
|
package/skills/hashnode/SKILL.md
CHANGED
|
@@ -145,3 +145,17 @@ gql 'query GetPost($id: ObjectId!) { post(id: $id) { title url views reactionCou
|
|
|
145
145
|
via status codes; always surface them.
|
|
146
146
|
- **Idempotency** — re-running `publishPost` creates a *new* post each time; to
|
|
147
147
|
change an existing one use `updatePost` with its `id`.
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
## Record the output
|
|
151
|
+
|
|
152
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
153
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
publish_artifact(kind="article", channel="hashnode", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
160
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
161
|
+
See `_shared/artifacts.md`.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: instagram
|
|
3
|
+
description: Publish images, videos, Reels or carousels to your Instagram professional account via the Instagram Content Publishing API, and read your own recent media. Use when the user wants to post to Instagram (photo / video / reel / carousel), cross-post a visual, or review their own Instagram posts. Instagram is image/video-only (no text-only posts). Auth uses an access token (BYOC). 支持 Instagram 图片 / 视频 / Reels / 轮播发布。
|
|
4
|
+
when_to_use: |
|
|
5
|
+
Trigger when the user wants to publish a photo, video, reel or carousel to
|
|
6
|
+
their Instagram professional (Business/Creator) account, or review their own
|
|
7
|
+
recent posts. Instagram only publishes image/video — there are no text-only
|
|
8
|
+
posts. Publishing posts as their real account — confirm caption + media first.
|
|
9
|
+
connections: [instagram]
|
|
10
|
+
allowed_tools: [Bash]
|
|
11
|
+
license: Apache-2.0
|
|
12
|
+
metadata:
|
|
13
|
+
author: acedatacloud
|
|
14
|
+
version: "1.0"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Call the **Instagram Graph API** (`graph.facebook.com`) with `curl + jq`. The
|
|
18
|
+
connector injects `$INSTAGRAM_ACCESS_TOKEN` (a token with
|
|
19
|
+
`instagram_content_publish` + `pages_read_engagement`; a Facebook Page token or
|
|
20
|
+
an Instagram-Login user token) and optionally `$INSTAGRAM_IG_USER_ID`. Never echo them.
|
|
21
|
+
|
|
22
|
+
Instagram publishes only **images / videos / reels** to a **professional**
|
|
23
|
+
(Business or Creator) account linked to a Facebook Page. There are no text-only posts.
|
|
24
|
+
|
|
25
|
+
### Resolve the Instagram account id
|
|
26
|
+
|
|
27
|
+
If `$INSTAGRAM_IG_USER_ID` is set, use it. Otherwise derive it from the linked Page:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
if [ -n "$INSTAGRAM_IG_USER_ID" ]; then
|
|
31
|
+
IGID="$INSTAGRAM_IG_USER_ID"
|
|
32
|
+
else
|
|
33
|
+
PAGE=$(curl -sS "https://graph.facebook.com/v21.0/me/accounts?access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.data[0].id')
|
|
34
|
+
IGID=$(curl -sS "https://graph.facebook.com/v21.0/$PAGE?fields=instagram_business_account&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.instagram_business_account.id')
|
|
35
|
+
fi
|
|
36
|
+
echo "ig_user_id=$IGID"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Errors are JSON with `error.message` / `error.code` — show them verbatim.
|
|
40
|
+
`401` / `OAuthException` → token expired or missing scope; a null `IGID` → the
|
|
41
|
+
token isn't linked to a professional IG account / Page (see Gotchas). Reconnect if needed.
|
|
42
|
+
|
|
43
|
+
## Publish a single image (two-step: create container → publish)
|
|
44
|
+
|
|
45
|
+
**Confirm the caption + image with the user first.** The `image_url` must be a
|
|
46
|
+
**public JPEG** URL (Instagram server-side cURLs it):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
CID=$(curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media" \
|
|
50
|
+
-d "image_url=https://cdn.acedata.cloud/xxxx.jpg" \
|
|
51
|
+
--data-urlencode "caption=One endpoint → posters, cards, mockups. #AI #API" \
|
|
52
|
+
-d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .id)
|
|
53
|
+
echo "container=$CID"
|
|
54
|
+
|
|
55
|
+
curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media_publish" \
|
|
56
|
+
-d "creation_id=$CID" -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq .
|
|
57
|
+
# → {"id":"<IG_MEDIA_ID>"}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Get the permalink to hand back to the user:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
curl -sS "https://graph.facebook.com/v21.0/<IG_MEDIA_ID>?fields=permalink&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .permalink
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Reels / video
|
|
67
|
+
|
|
68
|
+
Create with `media_type=REELS` + a public `video_url`, then **poll the container
|
|
69
|
+
status until FINISHED** before publishing (video processing takes time):
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
CID=$(curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media" \
|
|
73
|
+
-d "media_type=REELS" -d "video_url=https://cdn.acedata.cloud/xxxx.mp4" \
|
|
74
|
+
--data-urlencode "caption=..." -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .id)
|
|
75
|
+
|
|
76
|
+
# poll until the video finishes processing (up to ~5 min) BEFORE publishing —
|
|
77
|
+
# publishing an IN_PROGRESS container is rejected:
|
|
78
|
+
for i in $(seq 1 60); do
|
|
79
|
+
ST=$(curl -sS "https://graph.facebook.com/v21.0/$CID?fields=status_code&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .status_code)
|
|
80
|
+
echo "status=$ST"; [ "$ST" = "FINISHED" ] && break
|
|
81
|
+
[ "$ST" = "ERROR" ] || [ "$ST" = "EXPIRED" ] && { echo "container failed: $ST"; break; }
|
|
82
|
+
sleep 5
|
|
83
|
+
done
|
|
84
|
+
|
|
85
|
+
curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media_publish" \
|
|
86
|
+
-d "creation_id=$CID" -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Carousel (2–10 items)
|
|
90
|
+
|
|
91
|
+
Create each child with `is_carousel_item=true`, then a `media_type=CAROUSEL`
|
|
92
|
+
container with `children=<ID1>,<ID2>,...` + `caption`, then publish the carousel id.
|
|
93
|
+
|
|
94
|
+
## Gotchas
|
|
95
|
+
|
|
96
|
+
- **No text-only posts** — Instagram requires an image or video. Use a public
|
|
97
|
+
**JPEG** for images (PNG/other formats are rejected; extended JPEG like MPO/JPS too).
|
|
98
|
+
- **Professional account required** — a Business/Creator IG account linked to a
|
|
99
|
+
Facebook Page. If `instagram_business_account` is null, the account isn't a
|
|
100
|
+
professional account or isn't linked; the user must fix that in IG / Page settings.
|
|
101
|
+
- **Media must be a public URL** on a server Instagram can reach; local files
|
|
102
|
+
won't work. Host on cdn.acedata.cloud first.
|
|
103
|
+
- **Rate limit:** 100 API-published posts per 24h (a carousel counts as 1). Check
|
|
104
|
+
via `GET /$IGID/content_publishing_limit`.
|
|
105
|
+
- **Page Publishing Authorization (PPA):** some Pages must complete PPA before API
|
|
106
|
+
publishing works — surface the API error verbatim if it mentions PPA.
|
|
107
|
+
- API version: keep the `vXX.0` path current if you hit a version/deprecation error.
|
|
108
|
+
|
|
109
|
+
## Record the output
|
|
110
|
+
|
|
111
|
+
After you successfully publish and obtain the live permalink, call the built-in
|
|
112
|
+
`publish_artifact` tool ONCE so the user can track it in **My Outputs**:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
publish_artifact(kind="image", channel="instagram", title="<title>", url="<the REAL permalink>", status="delivered")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
119
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
120
|
+
See `_shared/artifacts.md`.
|
package/skills/juejin/SKILL.md
CHANGED
|
@@ -73,3 +73,17 @@ python3 $JJ publish --title "标题" --content-file a.md \
|
|
|
73
73
|
- Publishing without a category + tag is rejected in 审核; prefer `--draft-only`.
|
|
74
74
|
- **Never print `JUEJIN_COOKIES`** — it is full account access.
|
|
75
75
|
- **ToS**: acts only on the user's own account with their own captured cookie.
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## Record the output
|
|
79
|
+
|
|
80
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
81
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
publish_artifact(kind="article", channel="juejin", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
88
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
89
|
+
See `_shared/artifacts.md`.
|
package/skills/linkedin/SKILL.md
CHANGED
|
@@ -71,3 +71,17 @@ If the versioned endpoint is unavailable for the app, the older
|
|
|
71
71
|
Page posts need `w_organization_social` + an admin role (not in this connector).
|
|
72
72
|
- The `LinkedIn-Version` header is mandatory for `/rest/*`; a stale value
|
|
73
73
|
returns a version error — bump to the current `YYYYMM`.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
## Record the output
|
|
77
|
+
|
|
78
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
79
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
publish_artifact(kind="article", channel="linkedin", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
86
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
87
|
+
See `_shared/artifacts.md`.
|
package/skills/mastodon/SKILL.md
CHANGED
|
@@ -101,3 +101,17 @@ https://docs.joinmastodon.org/methods/media/
|
|
|
101
101
|
get `429`.
|
|
102
102
|
- `verify_credentials` returns HTML in fields like `note`; the plaintext source
|
|
103
103
|
lives under the `source` object.
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
## Record the output
|
|
107
|
+
|
|
108
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
109
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
publish_artifact(kind="message", channel="mastodon", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
116
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
117
|
+
See `_shared/artifacts.md`.
|
package/skills/medium/SKILL.md
CHANGED
|
@@ -93,3 +93,17 @@ to a link paragraph (never blocks the post).
|
|
|
93
93
|
genuinely expired (reconnect).
|
|
94
94
|
- **Never print `MEDIUM_COOKIES`** — it is full account access.
|
|
95
95
|
- **ToS**: acts only on the user's own account with their own captured cookie.
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
## Record the output
|
|
99
|
+
|
|
100
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
101
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
publish_artifact(kind="article", channel="medium", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
108
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
109
|
+
See `_shared/artifacts.md`.
|
package/skills/notion/SKILL.md
CHANGED
|
@@ -120,3 +120,17 @@ curl -sS -X POST "https://api.notion.com/v1/pages" \
|
|
|
120
120
|
- Most write failures (400/404) come from a property type mismatch —
|
|
121
121
|
e.g. sending `{"select": "Open"}` instead of `{"select": {"name": "Open"}}`.
|
|
122
122
|
Read the database schema once via `GET /v1/databases/<id>` if unsure.
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
## Record the output
|
|
126
|
+
|
|
127
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
128
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
publish_artifact(kind="document", channel="notion", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
135
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
136
|
+
See `_shared/artifacts.md`.
|
package/skills/reddit/SKILL.md
CHANGED
|
@@ -77,3 +77,17 @@ curl -sS -H "Authorization: Bearer $REDDIT_TOKEN" -H "User-Agent: $UA" \
|
|
|
77
77
|
- Respect rate limits: read the `X-Ratelimit-Remaining` response header; space
|
|
78
78
|
out bulk submits.
|
|
79
79
|
- Use `r/test` as a safe target when validating that the connection works.
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
## Record the output
|
|
83
|
+
|
|
84
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
85
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
publish_artifact(kind="message", channel="reddit", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
92
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
93
|
+
See `_shared/artifacts.md`.
|
package/skills/substack/SKILL.md
CHANGED
|
@@ -93,3 +93,17 @@ python3 $SUB publish --title "Title" --content-file post.md --send-email --confi
|
|
|
93
93
|
genuinely expired (reconnect); the CLI never retries a write.
|
|
94
94
|
- **Never print `SUBSTACK_COOKIES`** — it is full account access.
|
|
95
95
|
- **ToS**: acts only on the user's own account with their own captured cookie.
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
## Record the output
|
|
99
|
+
|
|
100
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
101
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
publish_artifact(kind="article", channel="substack", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
108
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
109
|
+
See `_shared/artifacts.md`.
|
package/skills/telegram/SKILL.md
CHANGED
|
@@ -122,3 +122,17 @@ user verbatim as the confirmation prompt.
|
|
|
122
122
|
return an error (no shareable link exists).
|
|
123
123
|
- **`edit`/`delete`** generally only apply to the user's own messages (admins can delete others
|
|
124
124
|
in groups they manage).
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
## Record the output
|
|
128
|
+
|
|
129
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
130
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
publish_artifact(kind="message", channel="telegram", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
137
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
138
|
+
See `_shared/artifacts.md`.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: threads
|
|
3
|
+
description: Publish text, image, video or carousel posts to your Threads (@threads) account via the official Threads API, and read your own recent posts. Use when the user wants to post to Threads, cross-post a short update / thread, attach an image or link, or review their own Threads posts. Auth uses a Threads access token (BYOC). 支持 Threads 文本 / 图片 / 视频 / 轮播发布与自有贴文读取。
|
|
4
|
+
when_to_use: |
|
|
5
|
+
Trigger when the user wants to publish a post to their Threads account or
|
|
6
|
+
review their own recent Threads posts. Threads is Meta's text-first social
|
|
7
|
+
app; the connector stores a Threads access token with threads_content_publish.
|
|
8
|
+
Posting publishes as their real account — confirm the text with the user first.
|
|
9
|
+
connections: [threads]
|
|
10
|
+
allowed_tools: [Bash]
|
|
11
|
+
license: Apache-2.0
|
|
12
|
+
metadata:
|
|
13
|
+
author: acedatacloud
|
|
14
|
+
version: "1.0"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
Call the **Threads API** (`graph.threads.net`) with `curl + jq`. The connector
|
|
18
|
+
injects one credential: `$THREADS_ACCESS_TOKEN` (a long-lived Threads access
|
|
19
|
+
token with the `threads_basic` + `threads_content_publish` scopes). Never echo it.
|
|
20
|
+
|
|
21
|
+
Resolve the caller's Threads user id once (every publish needs it):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ME=$(curl -sS "https://graph.threads.net/v1.0/me?fields=id,username&access_token=$THREADS_ACCESS_TOKEN")
|
|
25
|
+
TID=$(echo "$ME" | jq -r .id)
|
|
26
|
+
echo "$ME" # {"id":"<THREADS_USER_ID>","username":"..."}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Errors are JSON with `error.message` / `error.code` — show them verbatim.
|
|
30
|
+
`401` / `OAuthException` → the token expired or lacks scope; reconnect the
|
|
31
|
+
Threads connector.
|
|
32
|
+
|
|
33
|
+
## Publish a post (two-step: create container → publish)
|
|
34
|
+
|
|
35
|
+
**Confirm the text with the user first** (it publishes as their real account).
|
|
36
|
+
Text ≤ **500 characters** (emoji counted as UTF-8 bytes).
|
|
37
|
+
|
|
38
|
+
Step 1 — create a media container. Text-only (guard the 500-byte limit first):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
TEXT="Shipping one API for AI images → posters, cards, mockups. https://platform.acedata.cloud #AI #API"
|
|
42
|
+
[ "$(printf %s "$TEXT" | wc -c)" -le 500 ] || { echo "text exceeds Threads 500-byte limit — shorten it"; }
|
|
43
|
+
CID=$(curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads" \
|
|
44
|
+
--data-urlencode "media_type=TEXT" \
|
|
45
|
+
--data-urlencode "text=$TEXT" \
|
|
46
|
+
-d "access_token=$THREADS_ACCESS_TOKEN" | jq -r .id)
|
|
47
|
+
echo "container=$CID"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Image post — add `media_type=IMAGE` + a **public** `image_url` (Threads cURLs it
|
|
51
|
+
server-side, so it must be on a public server); video uses `media_type=VIDEO` + `video_url`:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
CID=$(curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads" \
|
|
55
|
+
--data-urlencode "media_type=IMAGE" \
|
|
56
|
+
-d "image_url=https://cdn.acedata.cloud/xxxx.jpg" \
|
|
57
|
+
--data-urlencode "text=caption here" \
|
|
58
|
+
-d "access_token=$THREADS_ACCESS_TOKEN" | jq -r .id)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Step 2 — publish the container. **Text posts publish immediately; for IMAGE /
|
|
62
|
+
VIDEO / carousel containers you MUST wait ≥30s first** so Threads can
|
|
63
|
+
fetch/process the upload — publishing too early fails or returns no id:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
sleep 30 # REQUIRED for IMAGE / VIDEO / carousel; skip for TEXT-only posts
|
|
67
|
+
curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads_publish" \
|
|
68
|
+
-d "creation_id=$CID" -d "access_token=$THREADS_ACCESS_TOKEN" | jq .
|
|
69
|
+
# → {"id":"<THREADS_MEDIA_ID>"}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If `threads_publish` returns no id, the container isn't ready yet — poll
|
|
73
|
+
`GET /v1.0/<CID>?fields=status&access_token=$THREADS_ACCESS_TOKEN` until
|
|
74
|
+
`status=FINISHED`, then retry publish.
|
|
75
|
+
|
|
76
|
+
Get the public URL of the published post and hand it to the user:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
curl -sS "https://graph.threads.net/v1.0/<THREADS_MEDIA_ID>?fields=id,permalink&access_token=$THREADS_ACCESS_TOKEN" | jq -r .permalink
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Carousel (2–20 items)
|
|
83
|
+
|
|
84
|
+
Create each child with `is_carousel_item=true`, then a `media_type=CAROUSEL`
|
|
85
|
+
container with `children=<ID1>,<ID2>,...`, then publish the carousel id. Links:
|
|
86
|
+
add `link_attachment=<URL>` (text-only posts, ≤5 links). Topic tag: `topic_tag=<TAG>`.
|
|
87
|
+
|
|
88
|
+
## List my recent posts
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
curl -sS "https://graph.threads.net/v1.0/$TID/threads?fields=id,text,permalink,timestamp&limit=20&access_token=$THREADS_ACCESS_TOKEN" | jq '.data'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Gotchas
|
|
95
|
+
|
|
96
|
+
- **500-char limit**; emoji count as their UTF-8 byte length.
|
|
97
|
+
- **Media must be a public URL** — Threads server-side cURLs `image_url`/`video_url`;
|
|
98
|
+
local files won't work. Upload to a public host / cdn.acedata.cloud first.
|
|
99
|
+
- **Wait ~30s before publishing media** containers (text publishes instantly); if
|
|
100
|
+
`threads_publish` doesn't return an id, poll `GET /<container-id>?fields=status`.
|
|
101
|
+
- **Rate limit:** 250 published posts per 24h per profile (a carousel counts as 1).
|
|
102
|
+
- Threads tokens differ from Facebook/Instagram tokens — they come from the
|
|
103
|
+
Threads OAuth flow on `graph.threads.net`, not `graph.facebook.com`.
|
|
104
|
+
|
|
105
|
+
## Record the output
|
|
106
|
+
|
|
107
|
+
After you successfully publish and obtain the live permalink, call the built-in
|
|
108
|
+
`publish_artifact` tool ONCE so the user can track it in **My Outputs**:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
publish_artifact(kind="message", channel="threads", title="<title>", url="<the REAL permalink>", status="delivered")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
115
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
116
|
+
See `_shared/artifacts.md`.
|
|
@@ -141,3 +141,17 @@ echo "media id=$MEDIA_ID"
|
|
|
141
141
|
- **Never publish silently.** Even if the user says "post it", prefer creating a
|
|
142
142
|
draft and returning the `wp-admin` edit link unless they explicitly asked to
|
|
143
143
|
go live.
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
## Record the output
|
|
147
|
+
|
|
148
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
149
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
publish_artifact(kind="article", channel="wordpress", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
156
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
157
|
+
See `_shared/artifacts.md`.
|
package/skills/x/SKILL.md
CHANGED
|
@@ -107,3 +107,17 @@ python3 $X delete --id 123456 --confirm # delete one of M
|
|
|
107
107
|
suspended. Keep volume human-like.
|
|
108
108
|
- **Never print `X_COOKIES`** — it is full account access.
|
|
109
109
|
- **DMs are intentionally not exposed** by this skill.
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
## Record the output
|
|
113
|
+
|
|
114
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
115
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
publish_artifact(kind="message", channel="x", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
122
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
123
|
+
See `_shared/artifacts.md`.
|
package/skills/zhihu/SKILL.md
CHANGED
|
@@ -218,3 +218,17 @@ python3 $BLOG edit-answer --id <answer-id> --content-file ans.html --confirm #
|
|
|
218
218
|
- **Scope**: Zhihu only. Other Chinese platforms (掘金 / CSDN / …) ship as their
|
|
219
219
|
own per-platform skills (e.g. `csdn`, `juejin`), each with its own connector —
|
|
220
220
|
not a `--platform` switch here.
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
## Record the output
|
|
224
|
+
|
|
225
|
+
After you successfully publish and obtain the live result URL, call the built-in
|
|
226
|
+
`publish_artifact` tool ONCE so the user can track this deliverable in **My Outputs**:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
publish_artifact(kind="article", channel="zhihu", title="<title>", url="<the REAL returned URL>", status="delivered")
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Use the real returned URL — never fabricate one. Call it once per published item,
|
|
233
|
+
only after delivery is confirmed; skip it (or use `status="failed"`) if publishing failed.
|
|
234
|
+
See `_shared/artifacts.md`.
|