Skip to content

feat(publish): allow uploading a skill folder directly - #757

Merged
XiaoSeS merged 2 commits into
mainfrom
feat/folder-upload
Aug 26, 2026
Merged

XiaoSeS merged 2 commits into
mainfrom
feat/folder-upload

Conversation

@FenjuFu

@FenjuFu FenjuFu commented Aug 25, 2026

Copy link
Copy Markdown
Member

What

Let publishers upload a skill folder directly, instead of hand-zipping it first — closes #737.

Why

Publishing only accepted a .zip. Skills on disk (and every local agent skill) are folders, and the "zip it up first" step routinely smuggles in tool/OS metadata (__MACOSX/, .DS_Store, …) that bloats the package and the file-count limit.

How

  • The publish dropzone gets an "Or select a folder" action. Picking a folder (webkitdirectory) hands the raw files to the publish flow, which packages them client-side into a clean .zip and feeds it into the existing upload path — no new endpoint, same validation.
  • folder-zip.ts is a small dependency-free ZIP writer (STORE method + CRC-32). Skill packages are small text files, so STORE keeps this free of any new npm dependency. It drops VCS/build/OS junk (.git/, .svn/, .hg/, node_modules/, __pycache__/, .DS_Store, ._*, Thumbs.db, …) that a real on-disk folder carries.
  • Paths are kept as-is (my-skill/SKILL.md); the server already strips a single root directory (SkillPackageArchiveExtractor.stripSingleRootDirectory) and ignores OS-metadata entries, so the archive lands exactly like a hand-made zip.

Scope / safety

  • Additive: UploadZone gains an optional onFolderSelect prop; existing usage is unchanged and the drag-a-zip path is untouched.
  • The folder picker's non-standard webkitdirectory/directory attributes are set imperatively (via a ref effect) to avoid an untyped JSX cast.
  • Packaging logic is isolated in folder-zip.ts and unit-tested (folder-zip.test.ts): CRC-32 against known ISO-HDLC vectors, local/central/EOCD ZIP structure, junk filtering, and the empty-folder error.
  • i18n keys added for en and zh.

Closes #737

Publishing required a hand-made .zip. Local agent skills live as folders,
and repackaging them by hand often smuggles in tool metadata (__MACOSX/,
.DS_Store, ...) that clutters the package (#737).

Add an "upload a folder" option to the publish dropzone: pick a folder
(webkitdirectory), and the browser packages it into a clean STORE-method
zip via a dependency-free writer, dropping VCS/build/OS junk (.git/,
node_modules/, __pycache__/, .DS_Store, ...). The resulting zip flows
through the exact same upload/publish path, and the server already strips
a single root directory, so paths are preserved as-is.

Packaging (folder-zip.ts) is isolated and unit-tested (CRC-32 vectors, zip
structure, junk filtering); the UploadZone gains an optional onFolderSelect
prop so existing callers are unaffected.

Closes #737

Signed-off-by: FenjuFu <92919259+FenjuFu@users.noreply.github.com>
@FenjuFu
FenjuFu force-pushed the feat/folder-upload branch from 198a907 to 0fbc55f Compare August 25, 2026 12:16
Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
@XiaoSeS
XiaoSeS force-pushed the feat/folder-upload branch from 647d77b to e1c18e8 Compare August 26, 2026 09:25
@XiaoSeS
XiaoSeS merged commit 3b5d438 into main Aug 26, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 希望支持选择文件夹即可上传

2 participants