@acedatacloud/skills 2026.628.3 → 2026.628.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acedatacloud/skills",
3
- "version": "2026.628.3",
3
+ "version": "2026.628.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",
@@ -257,9 +257,29 @@ ZH_UPLOADED_IMAGES = "https://zhuanlan.zhihu.com/api/uploaded_images"
257
257
  ZH_IMAGES = "https://api.zhihu.com/images"
258
258
  OSS_ENDPOINT = "https://zhihu-pics-upload.zhimg.com"
259
259
  OSS_BUCKET = "zhihu-pics"
260
- _ZHIMG = "zhimg.com" # a src already on Zhihu's CDN needs no re-upload
260
+ # A src already on Zhihu's own CDN needs no re-upload. uploaded_images hands back
261
+ # a pic-private.zhihu.com URL for draft-scoped images, so skip those too.
262
+ _ZHIMG_HOSTS = ("zhimg.com", "pic-private.zhihu.com")
261
263
  _IMG_SRC_RE = re.compile(r'(<img[^>]*?\ssrc=["\'])([^"\']+)(["\'])', re.IGNORECASE)
262
264
  _MD_IMG_RE = re.compile(r'(!\[[^\]]*\]\()(\s*<?)([^)\s>]+)(>?\s*\))')
265
+ # uploaded_images returns a DRAFT-SCOPED signed pic-private URL whose auth_key
266
+ # expires; reduce any Zhihu image URL to the durable public form Zhihu serves
267
+ # after publish (picx.zhimg.com/v2-<hash>.<ext>).
268
+ _ZH_IMG_HASH = re.compile(r'(v2-[0-9a-f]+)(?:~[^."?\']*)?\.(png|jpe?g|gif|webp)', re.IGNORECASE)
269
+
270
+
271
+ def _on_zhihu_cdn(src: str) -> bool:
272
+ # Match on the parsed host (not a substring) so an external host that merely
273
+ # contains "zhimg.com" (e.g. my-zhimg.com) isn't wrongly treated as hosted.
274
+ host = (urllib.parse.urlsplit(src).hostname or "") if src else ""
275
+ return any(host == h or host.endswith("." + h) for h in _ZHIMG_HOSTS)
276
+
277
+
278
+ def _canonical_zhimg(url):
279
+ if not url:
280
+ return url
281
+ m = _ZH_IMG_HASH.search(url)
282
+ return f"https://picx.zhimg.com/{m.group(1)}.{m.group(2).lower()}" if m else url
263
283
 
264
284
 
265
285
  def _raw(method, url, jar, *, headers=None, data=None, timeout=60):
@@ -312,7 +332,7 @@ def _upload_image_url(jar, src: str):
312
332
  except json.JSONDecodeError:
313
333
  return None
314
334
  if isinstance(d, dict) and d.get("src"):
315
- return d["src"]
335
+ return _canonical_zhimg(d["src"])
316
336
  return None
317
337
 
318
338
 
@@ -380,13 +400,13 @@ def _upload_image_binary(jar, data: bytes):
380
400
  upload_token = token_data.get("upload_token") or {}
381
401
  if upload_file.get("state") == 1: # already on Zhihu — just resolve its hash
382
402
  object_key = _wait_image_ready(jar, upload_file.get("image_id", ""))
383
- return f"https://pic4.zhimg.com/{object_key}" if object_key else None
403
+ return _canonical_zhimg(f"https://pic4.zhimg.com/{object_key}") if object_key else None
384
404
  object_key = upload_file.get("object_key", "")
385
405
  if not object_key or not _oss_put(object_key, data, upload_token):
386
406
  return None
387
407
  if data[:6] in (b"GIF87a", b"GIF89a"):
388
408
  object_key += ".gif"
389
- return f"https://pic4.zhimg.com/{object_key}"
409
+ return _canonical_zhimg(f"https://pic4.zhimg.com/{object_key}")
390
410
 
391
411
 
392
412
  def _download_image(src: str):
@@ -400,7 +420,7 @@ def _download_image(src: str):
400
420
  def count_images(content: str) -> int:
401
421
  srcs = {m.group(2) for m in _IMG_SRC_RE.finditer(content or "")}
402
422
  srcs |= {m.group(3) for m in _MD_IMG_RE.finditer(content or "")}
403
- return sum(1 for s in srcs if _ZHIMG not in s)
423
+ return sum(1 for s in srcs if not _on_zhihu_cdn(s))
404
424
 
405
425
 
406
426
  def rehost_images(jar, content: str):
@@ -410,7 +430,7 @@ def rehost_images(jar, content: str):
410
430
  stats = {"found": 0, "rehosted": 0, "failed": 0}
411
431
 
412
432
  def resolve(src: str) -> str:
413
- if not src or _ZHIMG in src:
433
+ if not src or _on_zhihu_cdn(src):
414
434
  return src
415
435
  if src in cache:
416
436
  return cache[src]