@acedatacloud/skills 2026.728.3 → 2026.728.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/x/SKILL.md +7 -1
- package/skills/x/scripts/x.py +50 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acedatacloud/skills",
|
|
3
|
-
"version": "2026.728.
|
|
3
|
+
"version": "2026.728.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",
|
package/skills/x/SKILL.md
CHANGED
|
@@ -81,7 +81,13 @@ the default.
|
|
|
81
81
|
On an actual auth error the cookie is expired — have the user reconnect at
|
|
82
82
|
<https://auth.acedata.cloud/user/connections>. A Cloudflare block is different:
|
|
83
83
|
reconnecting cookies does not fix it. Use `whoami` for identity checks; other
|
|
84
|
-
blocked endpoints need `X_PROXY` or the official X API. Do **not** loop-retry
|
|
84
|
+
blocked endpoints need `X_PROXY` or the official X API. Do **not** loop-retry a
|
|
85
|
+
Cloudflare block or an auth error.
|
|
86
|
+
|
|
87
|
+
A **404 is not an auth error.** X's identity endpoints 404 on roughly a quarter
|
|
88
|
+
of calls even with healthy cookies, on every account. `whoami` already retries
|
|
89
|
+
those internally, so if it still reports a 404, wait a moment and run it again —
|
|
90
|
+
do not tell the user to reconnect.
|
|
85
91
|
|
|
86
92
|
## Write commands — GATED (dry-run unless trailing `--confirm`)
|
|
87
93
|
|
package/skills/x/scripts/x.py
CHANGED
|
@@ -245,8 +245,52 @@ async def resolve_user(client, target: str):
|
|
|
245
245
|
|
|
246
246
|
# ── read commands ───────────────────────────────────────────────────
|
|
247
247
|
|
|
248
|
+
IDENTITY_ATTEMPTS = 4
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class _UnraisableSentinel(Exception):
|
|
252
|
+
"""Stands in for twikit's NotFound when twikit is absent, so the unit tests
|
|
253
|
+
(which mock the client entirely) can exercise these paths."""
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def not_found_error():
|
|
257
|
+
try:
|
|
258
|
+
from twikit.errors import NotFound
|
|
259
|
+
except Exception:
|
|
260
|
+
return _UnraisableSentinel
|
|
261
|
+
return NotFound
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
async def retry_flaky_not_found(client, call, what: str):
|
|
265
|
+
"""Run `call(client)`, retrying X's intermittent 404s on a fresh session.
|
|
266
|
+
|
|
267
|
+
X's identity endpoints 404 on roughly a quarter of calls even with healthy
|
|
268
|
+
cookies (measured over 20-trial batches on three separate accounts), so a
|
|
269
|
+
404 here is NOT an expired cookie. Returns (result, client) — the client is
|
|
270
|
+
replaced on each retry because reusing the failing session keeps 404ing.
|
|
271
|
+
"""
|
|
272
|
+
not_found = not_found_error()
|
|
273
|
+
last_error = None
|
|
274
|
+
for attempt in range(IDENTITY_ATTEMPTS):
|
|
275
|
+
if attempt:
|
|
276
|
+
await asyncio.sleep(0.6 * attempt)
|
|
277
|
+
client = make_client()
|
|
278
|
+
try:
|
|
279
|
+
return await call(client), client
|
|
280
|
+
except not_found as e:
|
|
281
|
+
last_error = e
|
|
282
|
+
die(
|
|
283
|
+
f"X returned 404 for {what} on {IDENTITY_ATTEMPTS} consecutive attempts. "
|
|
284
|
+
"That endpoint is intermittently flaky — a 404 is not an expired cookie, "
|
|
285
|
+
"so reconnecting will not help. Retry the same command in a moment. "
|
|
286
|
+
f"({last_error})"
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
|
|
248
290
|
async def cmd_whoami(client, args):
|
|
249
|
-
settings, _ = await
|
|
291
|
+
(settings, _), client = await retry_flaky_not_found(
|
|
292
|
+
client, lambda c: c.v11.settings(), "the authenticated account's settings"
|
|
293
|
+
)
|
|
250
294
|
authenticated_screen_name = settings.get("screen_name") if isinstance(settings, dict) else None
|
|
251
295
|
if not isinstance(authenticated_screen_name, str) or not re.fullmatch(
|
|
252
296
|
r"[A-Za-z0-9_]{1,15}", authenticated_screen_name
|
|
@@ -260,7 +304,11 @@ async def cmd_whoami(client, args):
|
|
|
260
304
|
f"connected X account is @{authenticated_screen_name}, not @{expected_screen_name}; "
|
|
261
305
|
"stopped without performing any write"
|
|
262
306
|
)
|
|
263
|
-
u = await
|
|
307
|
+
u, client = await retry_flaky_not_found(
|
|
308
|
+
client,
|
|
309
|
+
lambda c: c.get_user_by_screen_name(authenticated_screen_name),
|
|
310
|
+
f"@{authenticated_screen_name}'s profile",
|
|
311
|
+
)
|
|
264
312
|
result = fmt_user(u)
|
|
265
313
|
result.update(
|
|
266
314
|
{
|