@acedatacloud/skills 2026.720.1 → 2026.720.2

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.720.1",
3
+ "version": "2026.720.2",
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",
@@ -21,12 +21,19 @@ execution:
21
21
  - tabs
22
22
  - snapshot
23
23
  - screenshot
24
+ - element_info
24
25
  - navigate
25
26
  - click
26
27
  - click_at
28
+ - hover
27
29
  - form_input
30
+ - type_text
31
+ - select_option
32
+ - set_checked
28
33
  - key
29
34
  - scroll
35
+ - scroll_to
36
+ - wait_for
30
37
  - file_upload
31
38
  license: Apache-2.0
32
39
  metadata:
@@ -61,6 +68,7 @@ Read only the reference needed for the current request:
61
68
  | Image, video, long article, schedule, original, visibility, products | [publish](./references/publish.md) |
62
69
  | Like, favorite, comment, reply | [interactions](./references/interactions.md) |
63
70
  | Any uncertain write result or interrupted workflow | [reconciliation](./references/reconciliation.md) |
71
+ | Feature parity, route contracts, and selector diagnostics | [MCP parity](./references/mcp-parity.md) |
64
72
 
65
73
  For publish/search validation and feed-card parsing, use the shipped stdlib-only contract helper:
66
74
 
@@ -15,24 +15,27 @@ Use `parse-feed-snapshot` when a machine-checked card list is useful. Preserve `
15
15
 
16
16
  ## Recommendations
17
17
 
18
- Read the attached home/recommendation page. Scroll in bounded steps and read after each step. Return only the requested number of notes with title, author state, visible engagement, and canonical URL. Stop when enough results are collected, the page repeats, a warning appears, or the user limit is reached.
18
+ Navigate to `https://www.xiaohongshu.com/` (or the attached recommendation page), then wait in 300 ms bounded intervals for feed cards to hydrate, for at most 8 seconds. Read the attached page. Scroll in bounded steps and read after each step. Return only the requested number of notes with title, author state, visible engagement, and canonical URL. Stop when enough results are collected, the page repeats, a warning appears, the 8-second hydration window expires without cards, or the user limit is reached.
19
19
 
20
20
  ## Search and filters
21
21
 
22
22
  1. Normalize `{keyword, filters}` with `normalize-filters` before interacting. Supported filters are sort, note type, publish time, search scope, and location.
23
- 2. Read the current page, open the search control, fill the exact keyword, and submit with a fresh visible control or supported key.
24
- 3. Read the result page. Apply requested filters one at a time using fresh refs and verify each visible selected state.
25
- 4. Return bounded cards. Never invent query tokens, counts, or hidden IDs.
23
+ 2. Navigate to `https://www.xiaohongshu.com/search_result?keyword=<encoded>&source=web_explore_feed`, or use the visible search control when already attached there. Never invent a query token.
24
+ 3. Wait for visible results. To filter, hover the visible `筛选` control, wait for the panel, then choose exact labels one group at a time in this order: sort, note type, publish time, search scope, location. Use the normalized labels from `normalize-filters` rather than positional guesses.
25
+ 4. After every selection, wait for the panel/result state to settle and verify the exact selected label before continuing. If the hover panel closes, reacquire it; never click a stale option ref.
26
+ 5. Return bounded cards. Never invent query tokens, counts, or hidden IDs.
26
27
 
27
28
  ## Detail and comments
28
29
 
29
- Open a note from its fresh result ref or same-origin canonical URL. Read visible text, media labels, author, engagement, and the first visible comment batch. For more comments/replies, expand and scroll in bounded batches, reading after every transition and stopping at the requested limit. This is not a guaranteed full-comment export.
30
+ Open a note from its fresh result ref or same-origin canonical URL. Prefer clicking the fresh feed link so any required page token remains browser-local. Retry navigation at most three times with a short bounded delay, then stop. Read visible text, media labels, author, engagement, and the first visible comment batch.
31
+
32
+ For more comments/replies, first scroll to the comment area. In each bounded round: expand at most three visible `展开 N 条回复` controls, read the count, scroll the last visible comment into view, then scroll about 70% of one viewport. Stop at the requested count, visible end marker, no-comment state, 20 stagnant rounds, warning, or caller limit. Never copy the upstream 500-attempt default into chat automation.
30
33
 
31
34
  Pass the final semantic snapshot to `parse-note-snapshot --note-url <canonical-url>`. Preserve missing, ambiguous, and truncated states instead of filling absent fields. Only nodes with an explicit `comment` role are returned as structured comments; generic list items are never assumed to be comments.
32
35
 
33
36
  ## Profile
34
37
 
35
- Open the fresh author link from a result/detail page. Return visible profile text, followers/following/engagement totals, and bounded recent notes. Do not expose unrelated private account data.
38
+ Open the fresh author link from a result/detail page. For the current account, use the sidebar `我` profile channel rather than fabricating an ID. Return visible profile text, followers/following/engagement totals, and bounded recent notes. Profile notes can be grouped/lazy-loaded; flatten only visibly observed note batches. Do not expose unrelated private account data.
36
39
 
37
40
  Pass the final semantic snapshot to `parse-profile-snapshot --profile-url <canonical-url>` before reporting structured profile data. `visible_metrics` contains explicitly labeled profile metrics. Preserve `visible_counts` separately as unlabeled page counters; never reinterpret them as followers, following, likes, or favorites.
38
41
 
@@ -6,22 +6,22 @@ Always open and read the exact target note first. Derive it from the user's URL
6
6
 
7
7
  1. Read the target control's visible label and checked/pressed/selected state.
8
8
  2. If the current state already matches the explicit request, no-op and report it.
9
- 3. Otherwise click once, read again, and confirm the target state.
10
- 4. If state remains ambiguous, do not retry automatically.
9
+ 3. Otherwise click once, poll the fresh state every 500 ms for at most 4 seconds, and confirm the exact target state.
10
+ 4. If the state is readable and clearly unchanged, one retry is allowed because the action is reversible; never exceed two total clicks. If state cannot be read, do not retry.
11
11
 
12
12
  ## Comment
13
13
 
14
14
  1. Draft the exact comment and show the target note plus full text.
15
15
  2. Obtain explicit chat confirmation.
16
- 3. Open the visible editor, fill it, and read the draft back.
16
+ 3. Open the visible comment placeholder, then fill the visible contenteditable comment input and read the draft back.
17
17
  4. If the target or exact text differs, stop.
18
- 5. Click Send once after the confirmed preview, then follow reconciliation.
18
+ 5. Click the visible submit button once after the confirmed preview. Poll the visible comments for the exact text every 300 ms for at most 4 seconds; absence is an unknown/failed result, not success.
19
19
 
20
20
  ## Reply
21
21
 
22
- 1. Locate the exact visible target comment and author, expanding replies in bounded steps if needed.
22
+ 1. Locate the exact visible target comment and author. Prefer an exact comment ID when visible; otherwise match the explicitly confirmed user. Expand/scroll in bounded steps, stop at the end marker, and never search more than 100 rounds.
23
23
  2. Show the target and full reply preview; obtain explicit confirmation.
24
24
  3. Open that comment's reply control, fill the reply, and read the visible target/text back.
25
- 4. Submit once, then follow reconciliation.
25
+ 4. Submit once, then require the exact reply text to appear within 4 seconds before reporting success.
26
26
 
27
27
  Comments and replies are public account actions. The attached exact-origin session does not replace explicit chat preview confirmation.
@@ -2,21 +2,23 @@
2
2
 
3
3
  ## Status
4
4
 
5
- 1. Attach `https://www.xiaohongshu.com` and call `browser.snapshot` with that exact origin.
6
- 2. Determine login only from visible signed-in controls, profile links, or an explicit login prompt. Do not claim cryptographic account attestation.
7
- 3. If the state is ambiguous or the snapshot is truncated before account controls, ask the user to inspect the tab.
5
+ 1. Navigate or attach `https://www.xiaohongshu.com/explore` and wait up to 30 seconds in bounded intervals.
6
+ 2. Treat a visible sidebar profile channel (`我` / profile link) as signed in. Treat a visible login prompt or QR container as signed out. URL alone is not sufficient unless it visibly redirects to login.
7
+ 3. Determine login only from visible signed-in controls, profile links, or an explicit login prompt. Do not claim cryptographic account attestation.
8
+ 4. If `browser.snapshot` is unavailable on the dense page, use `browser.screenshot` for this status check. If neither proves the state, ask the user to inspect the tab.
8
9
 
9
10
  ## QR login
10
11
 
11
- 1. Open the visible login control with a fresh ref.
12
- 2. Read again. If a QR is present, call `browser.screenshot` and present the image; never extract QR payloads or session tokens.
13
- 3. The user scans locally. Wait in bounded intervals and read again until a visible signed-in state appears or the QR expires.
14
- 4. On expiry, ask before reopening a fresh QR. Never loop indefinitely.
12
+ 1. Open the visible login control with a fresh ref or screenshot-bound point.
13
+ 2. Read again. The upstream page contract renders the QR under the login container; call `browser.screenshot` and present the visible image, never the QR payload or session token.
14
+ 3. The user scans locally. Poll every 500 ms only through bounded `browser.wait_for`/fresh observations, with a maximum matching the visible QR expiry (never more than 5 minutes).
15
+ 4. Success requires the visible sidebar profile channel to appear. A disappeared QR alone is not success.
16
+ 5. On expiry, ask before reopening a fresh QR. Never loop indefinitely.
15
17
 
16
18
  ## Switch or sign out
17
19
 
18
20
  1. Show the visible current-account context and ask for explicit confirmation.
19
- 2. Use visible logout/switch controls with fresh refs after chat confirmation.
21
+ 2. Use visible logout/switch controls with fresh refs after chat confirmation. Do not copy the upstream Cookie-deletion shortcut; this Skill never clears or exports Cookies.
20
22
  3. Let the user complete credentials, SMS, QR, or verification locally.
21
23
  4. Read again and report only the visible resulting account state.
22
24
 
@@ -0,0 +1,49 @@
1
+ # Xiaohongshu MCP feature parity
2
+
3
+ This Skill benchmarks its business workflows against `xpzouying/xiaohongshu-mcp` commit
4
+ `a7d1f2f7f45e0b1c27de67c8f8a19131ba321725`. Reimplement the behavior through generic
5
+ `browser.*` capabilities; never copy its CDP runtime into the extension.
6
+
7
+ | Reference feature | Skill workflow |
8
+ |---|---|
9
+ | `check_login_status` | [login status](./login.md#status) |
10
+ | `get_login_qrcode` | [QR login](./login.md#qr-login) |
11
+ | `publish_content` | [image publish](./publish.md#execute) |
12
+ | `publish_with_video` | [video publish](./publish.md#execute) |
13
+ | long-article pipeline | [long article steps](./publish.md#execute) |
14
+ | `list_feeds` | [recommendations](./browse.md#recommendations) |
15
+ | `search_feeds` + five filter groups | [search and filters](./browse.md#search-and-filters) |
16
+ | `get_feed_detail` + comment loading | [detail and comments](./browse.md#detail-and-comments) |
17
+ | `user_profile` / `get_me` | [profile](./browse.md#profile) |
18
+ | `post_comment_to_feed` | [comment](./interactions.md#comment) |
19
+ | `reply_comment_in_feed` | [reply](./interactions.md#reply) |
20
+ | `like_feed` / unlike | [like and favorite](./interactions.md#like-and-favorite) |
21
+ | `favorite_feed` / unfavorite | [like and favorite](./interactions.md#like-and-favorite) |
22
+
23
+ ## Selector recognition hints
24
+
25
+ These are Xiaohongshu-specific diagnostics owned by this Skill. Use visible semantics first and reacquire
26
+ fresh refs after every transition.
27
+
28
+ - Creator mode tabs: `div.creator-tab`, exact text `上传图文`, `上传视频`, `写长文`.
29
+ - Upload input: `input.upload-input`, fallback single visible/associated `input[type=file]`.
30
+ - Image completion: `.img-preview-area .pr` count.
31
+ - Image/video title: placeholder containing `填写标题`, fallback visible title input.
32
+ - Long-title field: `textarea.d-text[placeholder="输入标题"]`.
33
+ - Body/editor: `div.tiptap.ProseMirror`, fallback visible `div.ProseMirror[contenteditable=true]`.
34
+ - Publish: enabled `xhs-publish-btn`, fallback visible `.publish-page-publish-btn button.bg-red`.
35
+ - Comment opener/input/submit: `div.input-box div.content-edit span`, `p.content-input`, `div.bottom button.submit`.
36
+ - Like/favorite: `.like-lottie`, `.collect-icon`; always verify resulting state.
37
+
38
+ Selectors are recognition hints, not permission to run arbitrary JavaScript or CSS queries. If generic
39
+ browser observations cannot identify a unique visible target, use a screenshot-bound action or stop.
40
+
41
+ ## Deliberate non-parity
42
+
43
+ Do not import upstream behaviors that violate the local-browser security boundary:
44
+
45
+ - no Cookie deletion/export or account state reset;
46
+ - no arbitrary CDP/evaluate, remote debugging port, or headless profile;
47
+ - no local filesystem paths or direct URL downloads in `browser.file_upload`;
48
+ - no hidden `window.__INITIAL_STATE__` extraction; report only visible browser observations;
49
+ - no 500-round unattended comment crawling; all loops are bounded and user-request limited.
@@ -20,13 +20,15 @@ Show the exact normalized preview: post type, title, full body, tags, media name
20
20
  ## Execute
21
21
 
22
22
  1. Ask the user to open `https://creator.xiaohongshu.com`, attach that tab, and locally verify the signed-in account.
23
- 2. Read the page and stop on warnings or unexpected account context.
24
- 3. Select image, video, or long-article mode using fresh refs.
25
- 4. Upload approved resource IDs through `browser.file_upload`, or wait for the user to select local media. Read until exact filenames/thumbnails and processing completion are visible.
26
- 5. Fill title/body using fresh refs. For rich-text editors, read immediately after input; if the exact value is not visible, stop rather than repeatedly injecting it.
27
- 6. Add tags/topics, template/layout, products, visibility, originality, and schedule one at a time. Read and verify each state.
28
- 7. Before the final action, read again and compare every visible field with the confirmed preview. Stop on mismatch.
29
- 8. Click Publish/Schedule exactly once after the final confirmed chat preview.
30
- 9. Follow [reconciliation](./reconciliation.md). Report success only from a visible success state or destination, and include the canonical URL when available.
23
+ 2. Navigate to `https://creator.xiaohongshu.com/publish/publish?source=official`. Wait for load, then allow two seconds for creator widgets and one bounded DOM-settle interval. Read or screenshot the page and stop on warnings, login redirects, or unexpected account context.
24
+ 3. Select mode by exact visible tab text: `上传图文`, `上传视频`, or `写长文`. Prefer a fresh semantic ref; if the tab is visually blocked by a popover, stop for user inspection instead of deleting page nodes. Verify the selected mode after clicking.
25
+ 4. For image posts, upload one approved resource at a time and wait until the visible preview count reaches the submitted count before the next resource (up to 60 seconds per image). For video, wait until processing completes and Publish becomes enabled, up to 10 minutes. If resource resolution is unavailable, wait for the user to select local media and verify the same preview/processing state.
26
+ 5. Fill the image/video title using the visible title textbox (recognition hints: placeholder containing `填写标题`, then the single visible title input fallback). Fill body in the visible TipTap/ProseMirror contenteditable editor. Use `browser.form_input` for replacement or focus with `browser.click`/`click_at` then `browser.type_text` for rich text. Read immediately after each field; stop if the exact normalized value is not visible.
27
+ 6. Limit tags to the first 10 confirmed tags. Insert them one at a time, close any topic suggestion popover by focusing the title, and verify visible chips/text before continuing.
28
+ 7. Configure options one at a time and verify each exact state: schedule (1 hour–14 days), visibility (`公开可见`, `仅自己可见`, `仅互关好友可见`), originality, and products. If originality was requested but cannot be confirmed, abort rather than publishing non-original. Bind a product only when the exact intended product is visibly selected; never accept a first fuzzy match silently.
29
+ 8. For long article: choose `写长文` → `新的创作`; fill `输入标题` textarea and ProseMirror body; click `一键排版`; enumerate visible template names; select the confirmed template and verify its selected state; click `下一步`; then fill the separate publish-page description editor.
30
+ 9. Before the final action, read or screenshot again and compare media count, title, full body, tags, options, products, and schedule with the confirmed preview. Stop on mismatch.
31
+ 10. Locate Publish through two page generations: visible enabled `xhs-publish-btn` widget first, then visible legacy red Publish button. Reject `submit-disabled=true`, `disabled`, `aria-disabled=true`, or disabled styling. Click exactly once after the final confirmed chat preview.
32
+ 11. Follow [reconciliation](./reconciliation.md). Immediate success requires leaving `/publish/publish` or a visible success destination within 15 seconds. Remaining on the form is not success. Return the canonical note URL when visible.
31
33
 
32
34
  Never mix image/video media unless the visible current UI explicitly supports it. Bind products only when the account visibly exposes the feature and the exact selected products appear in the final preview.
@@ -12,4 +12,12 @@ Use this after timeout, disconnect, stale ref, navigation, an ambiguous result,
12
12
  5. If `not_applied`, reversible actions may be attempted once from the verified state. Irreversible actions require a fresh preview and renewed chat confirmation.
13
13
  6. If `unknown`, stop and ask the user to inspect the local tab. Never retry publish, schedule, comment, or reply while unknown.
14
14
 
15
+ Action-specific success signals benchmarked from the local-browser workflow:
16
+
17
+ - Image upload: preview count reaches the submitted image count; a file-input event alone is not success.
18
+ - Video upload: Publish becomes enabled after processing; file selection alone is not success.
19
+ - Publish/schedule: URL leaves `/publish/publish` or a visible success destination appears within 15 seconds.
20
+ - Comment/reply: the exact submitted text renders in the comments area within 4 seconds.
21
+ - Like/favorite: the visible/semantic state equals the requested boolean; click completion alone is not success.
22
+
15
23
  Preserve the page on CAPTCHA, moderation, rate limit, account restriction, or unusual-activity warnings. Do not dismiss, solve, bypass, or retry around them.
@@ -12,6 +12,7 @@ REFERENCES = {
12
12
  "publish.md",
13
13
  "interactions.md",
14
14
  "reconciliation.md",
15
+ "mcp-parity.md",
15
16
  }
16
17
  EXPECTED_ORIGINS = {
17
18
  "https://www.xiaohongshu.com",
@@ -21,12 +22,19 @@ EXPECTED_CAPABILITIES = {
21
22
  "tabs",
22
23
  "snapshot",
23
24
  "screenshot",
25
+ "element_info",
24
26
  "navigate",
25
27
  "click",
26
28
  "click_at",
29
+ "hover",
27
30
  "form_input",
31
+ "type_text",
32
+ "select_option",
33
+ "set_checked",
28
34
  "key",
29
35
  "scroll",
36
+ "scroll_to",
37
+ "wait_for",
30
38
  "file_upload",
31
39
  }
32
40
  DEPLOYED_BROWSER_TOOLS = {
@@ -140,8 +148,8 @@ def test_browser_skill_matches_complete_local_runtime() -> None:
140
148
  assert "ask the user to open `https://creator.xiaohongshu.com`" in text
141
149
  assert "opaque resource ids" in text
142
150
  assert "trusted_input" not in _nested_list(_frontmatter(SKILL.read_text(encoding="utf-8")), "capabilities")
143
- assert "browser.read_page" not in text
144
- assert "browser.wait" not in text
151
+ assert not re.search(r"\bbrowser\.read_page\b", text)
152
+ assert not re.search(r"\bbrowser\.wait\b", text)
145
153
  assert "local approval" not in text
146
154
  assert "publish image, video, or long-article notes" in text
147
155
  assert "long_article" in text
@@ -164,4 +172,48 @@ def test_browser_skill_matches_complete_local_runtime() -> None:
164
172
  assert "content planning" in text
165
173
  assert "reconciliation after uncertain browser writes" in text
166
174
  assert "stop on warning" in text
167
- assert "explicit confirmation" in text
175
+ assert "explicit confirmation" in text
176
+
177
+
178
+ def test_upstream_mcp_feature_parity_and_skill_ownership() -> None:
179
+ text = "\n".join(
180
+ path.read_text(encoding="utf-8")
181
+ for path in [SKILL, *(SKILL_DIR / "references").glob("*.md")]
182
+ ).casefold()
183
+
184
+ for feature in (
185
+ "check_login_status",
186
+ "get_login_qrcode",
187
+ "publish_content",
188
+ "publish_with_video",
189
+ "list_feeds",
190
+ "search_feeds",
191
+ "get_feed_detail",
192
+ "user_profile",
193
+ "get_me",
194
+ "post_comment_to_feed",
195
+ "reply_comment_in_feed",
196
+ "like_feed",
197
+ "favorite_feed",
198
+ ):
199
+ assert feature in text
200
+
201
+ for invariant in (
202
+ "上传图文",
203
+ "上传视频",
204
+ "写长文",
205
+ "新的创作",
206
+ "一键排版",
207
+ "xhs-publish-btn",
208
+ "submit-disabled=true",
209
+ "img-preview-area",
210
+ "10 minutes",
211
+ "15 seconds",
212
+ "4 seconds",
213
+ "never exceed two total clicks",
214
+ ):
215
+ assert invariant.casefold() in text
216
+
217
+ assert "a7d1f2f7f45e0b1c27de67c8f8a19131ba321725" in text
218
+ assert "no arbitrary cdp/evaluate" in text
219
+ assert "no cookie deletion/export" in text