SuperAPI AI Directory

media-upload

Design & creation

View repository

Updated 10-15 20:24

About this skill

media-upload — media upload (images/videos), outputs raw.githubusercontent.com URL

Upload media files (screenshots, animated images, screen recordings — single or whole directory) to the public image-hosting repo (default ArcBlock/loop-agent-assets), returnsanonymously accessible's raw.githubusercontent.com/.../main/... URL。

Output language: Chinese; code / paths / commands stay in the original text.

⚠️ Upload is unified, embedding is not (the easiest pitfall to hit)

Uploading is the same set for image/video; but how to embed in GitHub markdown is split by type:

Type Extension Embedding method
Image png / jpg ![](<raw-url>) Inline display(#1334)
Animated image gif ![](<raw-url>) Inline playback(gif is image/gif, same path as images)
Video webm / mp4 / mov Link [▶ 录屏](<raw-url>), or best-effort <video src=...>;Never ![](x.webm)— GitHub will not render raw video as a player,![]() will only break the image

The criterion only looks atextension:.png/.jpg/.gif → ![]();.webm/.mp4/.mov → link.

Mechanism = two generic scripts in the plugin (they run the same for any repo, automatically detecting the source repo from git remote , landing in <slug>/<ctx>/)

First resolve the plugin root; the scripts are all under its scripts/ :

PLUGIN="${AGENTLOOP_ROOT:-$HOME/.claude/plugins/marketplaces/arcblock-agent-skills/plugins/agentloop}"
  • Single file:bash "$PLUGIN/scripts/gh-upload-media.sh" <media> [name] → automatically choose the write channel (gh contents API / git push) → content-type=image/*|video/* gate → stdout prints the raw.githubusercontent/main URL.
  • Whole directory:SCREENSHOT_DIR=<dir> CONTEXT=<ctx> bash "$PLUGIN/scripts/gh-upload-dir.sh" → traverse the directory (png/jpg/jpeg/gif/webm/mp4/mov) and call the above one for each → stdout one per line filename\turl; if any fails, append a line UPLOAD_FAILED\t<原因>(always exit 0, on failure look at this line, not the exit code).

Usage

/agentloop:media-upload <dir>          # 上传目录下所有媒体 → filename\turl map
/agentloop:media-upload <file>         # 单个(图片或视频)

# 消费方 skill 的 bash 里直接调脚本(自动化调机制、不调 slash 命令):
SCREENSHOT_DIR="$SHOT_DIR" CONTEXT="pr${PR}" bash "$PLUGIN/scripts/gh-upload-dir.sh" > url-map.tsv

After getting the map, follow the table above tosplit the embedding. When a UPLOAD_FAILED line is received, display at the top of the report > ⚠️ 媒体上传失败 — <原因> and downgrade to SendUserFile direct delivery (cannot embed, but does not produce broken files).

When neither uploader channel is available: browser native attachment upload (third-layer fallback, issue #3010)

SendUserFile only sends the file to the person in the current conversation,will notlet the evidence land on GitHub — the PR/issue still has no verifiable screenshot. This kind of review gating (ui-verify 's UI evidence gate is the most typical) requires evidencepersistently published on GitHub,gh and the image-hosting repo clone are both unavailable, the only deterministic and repeatable fallback isdriving a browser already logged into GitHubto go through native attachment upload (this round actually produced the screenshot evidence for arc#2991 / arcblock-site#165 / Site PR #166):

  1. Open the comment box of the target PR/issue, trigger the file chooser (drag and drop or click the attach button), and select the local media file.
  2. GitHub uploads the file to its own attachment CDN, returns https://github.com/user-attachments/assets/<uuid> (or the older user-images.githubusercontent.com/...) URL and automatically inserts the reference into the comment body.
  3. Before submitting, use a browser screenshot / read the DOM to confirm the media has rendered as a visible image/video, not a broken link — do not assume the upload succeeded.
  4. Post to both the PR and its associated issue(Fixes #<n> / Part of #<n>), do not post in only one place.

This URL family (github.com/user-attachments/assets/…、user-images.githubusercontent.com/…) is, like raw.githubusercontent.com/<repo>/main/… , gated downstream (e.g., .claude/skills/ui-verify/scripts/gate-comment.ts 's isPublishedUrl()) aspublishedevidence; local file paths,SendUserFile attachments, or any URL not verified as anonymously readable do not count—upload/publish failures must never be described by downstream reports as "verification complete", if it should be labeled BLOCKED/"evidence missing" then label it, without using neutral wording to obscure it (terminology consistent with ui-verify/pr-review/pr-sweep/issue-review ).

This fallback requiresan authenticated GitHub browser session, which is at a different level from gh-upload-media.sh 's two automated channels—it is not always feasible in every environment; when infeasible, degrade per the previous section to SendUserFile, and consumer gating treats it as "evidence missing" and must not let it through.

Why it must be raw.githubusercontent.com/main (the script already enforces this, don't change it yourself)

  • #1334: the GitHub MCP write side (add_issue_comment / issue_write)'s sanitizer strips ![](url) down to a plain link— the only exception is host=raw.githubusercontent.com and ref=main. Never use cdn.jsdelivr.net, and never use a session branch ref. (gh pr comment / gh issue comment 's comments are not subject to this restriction, but uniformly using raw.githubusercontent/main is safe for both posting channels.)
  • #1079: the MCP file write tool (create_or_update_file / push_files) double base64-encodes binarySecondary base64 encoding → it is stored as an ASCII string, not media.Media binaries must never go through any MCP write tool—the script goes through the gh contents API or git push, and does a content-type=image/*|video/* spot check on the returned URL (anything other than the two = double-encoded/corrupted, judged a failure).

Dual channels (the script selects automatically, callers need not care)

  • Channel A — gh contents API:gh used when it exists and has write permission to the image-hosting repo (local PAT / token with write permission); with transient 5xx retries.
  • Channel B — git push: when there is no gh(or no write permission),cp into the already-cloned image-hosting repo workspace ($ASSETS_REPO_DIR or probe ~/loop-agent-assets etc.) → commit + push origin main(with fetch+rebase retries). In a cloud routine, the gh token is a placeholder (403 for write APIs to this org, #1334), and this is the path taken—provided the image-hosting repo is configured as a second git source.

If neither channel is available → the script exits 2 → consumers degrade to SendUserFile。

Consumers

  • test-sweep(arc)、ui-verify(arcblock-site, and in the future did) etc. call in their own bash gh-upload-dir.sh。
  • The mechanism is always those two scripts, don't hand-roll for f in *.png loops in each repo(arc and arcblock-site each wrote their own copy and they have drifted—#1037). The human-readable doctrine + discoverable entry point is this skill.