@acedatacloud/skills 2026.703.4 → 2026.703.6

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.703.4",
3
+ "version": "2026.703.6",
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",
@@ -10,6 +10,7 @@ when_to_use: |
10
10
  notes, so create / append / move / delete are GATED behind an explicit
11
11
  confirmation.
12
12
  allowed_tools: [Bash]
13
+ surfaces: [mac]
13
14
  license: Apache-2.0
14
15
  compatibility: macOS-only. No API token, no connector — Apple Notes has no cloud API. Drives the local Notes.app via AppleScript (osascript); zero external dependencies (Python 3 standard library only). Requires granting Automation access to Notes.app on first run. Does not call api.acedata.cloud.
15
16
  metadata:
@@ -22,8 +23,15 @@ metadata:
22
23
  Drives the user's **real** Apple Notes through `Notes.app` on macOS. Apple never
23
24
  shipped a cloud API for Notes, so there is nothing to OAuth into and no token to
24
25
  inject — this skill runs **on the user's own Mac** and talks to Notes.app with
25
- AppleScript (`osascript`). It works when Claude Code runs on macOS directly, or
26
- remotely through a CodingBridge node running on the user's Mac.
26
+ AppleScript (`osascript`). It works wherever an agent runs on macOS: the
27
+ **AceDataCloud desktop app** (which executes local tools / local MCP on the
28
+ user's Mac), Claude Code on macOS, or a CodingBridge node on the user's Mac.
29
+
30
+ > **`surfaces: [mac]`** in the frontmatter marks this skill as **macOS-desktop
31
+ > only** — it cannot run on the web / iOS / Android / Windows surfaces (there is
32
+ > no local `Notes.app` there). The skill/connector directory UI reads this to
33
+ > badge the card ("macOS desktop") and steer users to install it from the macOS
34
+ > desktop app. Absent `surfaces`, a skill is assumed available everywhere.
27
35
 
28
36
  The skill ships [`scripts/notes.py`](scripts/notes.py) — self-contained, Python
29
37
  **standard library only** (it shells out to `osascript`; no `pip install`, no
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: hashnode
3
+ description: Publish, update and read blog posts on Hashnode via its GraphQL API. Use when the user mentions Hashnode, publishing a blog post to Hashnode, cross-posting an article to their Hashnode blog, saving a Hashnode draft, updating a published Hashnode post, or listing their Hashnode publications and posts.
4
+ when_to_use: |
5
+ Trigger when the user wants to publish a Markdown article to their
6
+ Hashnode blog, save it as a draft, update a previously published
7
+ post, or list / inspect their own Hashnode publications and posts.
8
+ The connector stores a Hashnode Personal Access Token with full
9
+ account access — confirm before publishing publicly (you can save a
10
+ draft first with the createDraft mutation).
11
+ connections: [hashnode]
12
+ allowed_tools: [Bash]
13
+ license: Apache-2.0
14
+ metadata:
15
+ author: acedatacloud
16
+ version: "1.0"
17
+ ---
18
+
19
+ Call the **Hashnode Public GraphQL API** with `curl + jq`. The user's Personal
20
+ Access Token is in `$HASHNODE_TOKEN`. Single endpoint: `https://gql.hashnode.com`
21
+ (always `POST` a JSON body `{query, variables}`).
22
+
23
+ Every request needs these headers:
24
+
25
+ ```
26
+ Authorization: $HASHNODE_TOKEN # raw token — NO "Bearer " prefix
27
+ Content-Type: application/json
28
+ ```
29
+
30
+ GraphQL always returns HTTP `200`; real failures live in the JSON `errors`
31
+ array — always inspect it and show it verbatim. An `errors` entry mentioning
32
+ `Unauthorized` / `not authenticated` means the token is invalid → the user must
33
+ re-connect the Hashnode connector.
34
+
35
+ Helper — send a query/mutation (`$1` = query string, `$2` = variables JSON):
36
+
37
+ ```bash
38
+ gql() {
39
+ jq -n --arg q "$1" --argjson v "${2:-null}" '{query:$q, variables:$v}' \
40
+ | curl -sS -X POST https://gql.hashnode.com \
41
+ -H "Authorization: $HASHNODE_TOKEN" \
42
+ -H "Content-Type: application/json" \
43
+ -d @-
44
+ }
45
+ ```
46
+
47
+ ## Always start by confirming the token and finding the publication id
48
+
49
+ `publishPost` / `createDraft` need a `publicationId`. Fetch the account and its
50
+ publications first (a user can have several blogs):
51
+
52
+ ```bash
53
+ gql 'query { me { id username publications(first: 10) { edges { node { id title url } } } } }' \
54
+ | jq '{me: .data.me.username, publications: [.data.me.publications.edges[].node | {id, title, url}], errors: .errors}'
55
+ ```
56
+
57
+ Pick the target blog's `id` (that is the `publicationId`). If the user has
58
+ exactly one publication, use it; otherwise ask which blog to post to.
59
+
60
+ ## Publish a post
61
+
62
+ **Confirm with the user before publishing publicly.** If they are not sure, save
63
+ a draft first (see below). `tags` is required — supply 1–5 tags, each as
64
+ `{name, slug}` (slug lowercase, no spaces).
65
+
66
+ ```bash
67
+ PUB_ID="PUBLICATION_ID" # from the me query above
68
+ TITLE="My title"
69
+ BODY_MD="$(cat article.md)" # full Markdown body
70
+
71
+ VARS=$(jq -n --arg p "$PUB_ID" --arg t "$TITLE" --arg b "$BODY_MD" '{
72
+ input: {
73
+ publicationId: $p,
74
+ title: $t,
75
+ contentMarkdown: $b,
76
+ tags: [{name:"AI", slug:"ai"}, {name:"Web Development", slug:"web-development"}]
77
+ }
78
+ }')
79
+
80
+ gql 'mutation PublishPost($input: PublishPostInput!) {
81
+ publishPost(input: $input) { post { id slug url title } }
82
+ }' "$VARS" | jq '{post: .data.publishPost.post, errors: .errors}'
83
+ ```
84
+
85
+ Useful optional `input` fields:
86
+
87
+ - `subtitle` — post subtitle.
88
+ - `slug` — custom URL slug (otherwise derived from the title).
89
+ - `canonicalUrl` / `originalArticleURL` — when cross-posting, point SEO back to
90
+ the original source. Set this whenever the same article also lives elsewhere.
91
+ - `coverImageOptions: { coverImageURL: "https://..." }` — cover image.
92
+ - `publishedAt` — ISO-8601 timestamp to backdate; `disableComments` etc. live
93
+ under `settings`.
94
+
95
+ ## Save a draft (safe, non-public)
96
+
97
+ Use this when the user has not explicitly approved public publishing:
98
+
99
+ ```bash
100
+ VARS=$(jq -n --arg p "$PUB_ID" --arg t "$TITLE" --arg b "$BODY_MD" '{
101
+ input: { publicationId: $p, title: $t, contentMarkdown: $b }
102
+ }')
103
+
104
+ gql 'mutation CreateDraft($input: CreateDraftInput!) {
105
+ createDraft(input: $input) { draft { id slug title } }
106
+ }' "$VARS" | jq '{draft: .data.createDraft.draft, errors: .errors}'
107
+ ```
108
+
109
+ ## Update a published post
110
+
111
+ `updatePost` needs the post `id` (from `publishPost`, or the list query below):
112
+
113
+ ```bash
114
+ VARS=$(jq -n --arg id "POST_ID" --arg b "$(cat article.md)" '{
115
+ input: { id: $id, contentMarkdown: $b }
116
+ }')
117
+
118
+ gql 'mutation UpdatePost($input: UpdatePostInput!) {
119
+ updatePost(input: $input) { post { id url title } }
120
+ }' "$VARS" | jq '{post: .data.updatePost.post, errors: .errors}'
121
+ ```
122
+
123
+ ## List / inspect my posts
124
+
125
+ ```bash
126
+ gql 'query { me { posts(pageSize: 20, page: 1) { nodes { id title slug url views reactionCount responseCount publishedAt } } } }' \
127
+ | jq '[.data.me.posts.nodes[] | {id, title, url, views, reactions: .reactionCount, responses: .responseCount}]'
128
+ ```
129
+
130
+ Single post with full content + stats:
131
+
132
+ ```bash
133
+ gql 'query GetPost($id: ObjectId!) { post(id: $id) { title url views reactionCount responseCount content { markdown } } }' \
134
+ "$(jq -n --arg id "POST_ID" '{id:$id}')" | jq '.data.post | {title, url, views, reactions: .reactionCount}'
135
+ ```
136
+
137
+ ## Gotchas
138
+
139
+ - **No `Bearer` prefix** — the `Authorization` header carries the raw token.
140
+ - **`publicationId` is mandatory** for publishing/drafting — never guess it, read
141
+ it from the `me` query.
142
+ - **`tags` is required on `publishPost`** — supply at least one `{name, slug}`;
143
+ slug must be lowercase with hyphens (e.g. `machine-learning`).
144
+ - **`errors` on HTTP 200** — GraphQL reports failures in the `errors` array, not
145
+ via status codes; always surface them.
146
+ - **Idempotency** — re-running `publishPost` creates a *new* post each time; to
147
+ change an existing one use `updatePost` with its `id`.