fix(ci): unblock release + single-source skills via Vite plugin#93
Merged
JamesLawton merged 6 commits intomainfrom Apr 21, 2026
Merged
fix(ci): unblock release + single-source skills via Vite plugin#93JamesLawton merged 6 commits intomainfrom
JamesLawton merged 6 commits intomainfrom
Conversation
The release workflow was failing at the GraphQL-payload stage with `/usr/bin/jq: Argument list too long` whenever a release touched more than a handful of sizeable files. The base64-encoded contents of every changed file were being passed to jq as a single `--argjson` value, which blows past Linux's ~128 KB per-argument ARG_MAX ceiling once a few CHANGELOG / SKILL.md updates accumulate. Spill the additions and deletions JSON to temp files and load them via `--slurpfile`, unwrapping with `$additions[0]` / `$deletions[0]`. The GraphQL body shape is unchanged; only the jq transport is different. Temp files are added to the existing EXIT trap.
5417c91 to
73a7d9d
Compare
73a7d9d to
692908e
Compare
692908e to
05997e1
Compare
@polygonlabs/agent-cli no longer ships a skills/ directory inside the published tarball. Installing the CLI via npm has never been the agent-facing skill install path — the recommended flow is `npx skills add https://github.com/0xPolygon/polygon-agent-cli`, which reads from the GitHub repo, not from npm. The bundled copy was vestigial: no CLI code reads it, no postinstall hook registers it, Claude Code does not auto-discover skills from installed npm packages, and the `skills` CLI (vercel-labs/skills) has no npm-package resolver at all — its `parseSource` function accepts GitHub/GitLab/local paths only. Removing it also deletes the duplicated copies under packages/connector-ui/public/ (root SKILL.md, skills/ tree, and per-sub-skill root mirrors) and packages/polygon-agent-cli/skills/ that the pre-commit hook was keeping in sync. The sync hook itself goes too — nothing left to sync. skills/ at the repo root is now the single source of truth. Note: this is technically a published-surface change — the tarball has shipped the skills/ path since 0.1.2. Pre-1.0 semver accepts surface changes in minor bumps, so this is intentionally NOT marked with a `!` or BREAKING CHANGE footer; @polygonlabs/agent-cli will bump 0.8.0 -> 0.9.0. No consumer has been found in or outside the repo that reads the bundled path. A following commit adds a Vite plugin that serves the CDN URL surface (/SKILL.md, /skills/*, /<sub-skill>/SKILL.md) directly from skills/ at build time, so the agentconnect URLs keep resolving with no committed duplicates.
A small Vite plugin (mirrorSkills) mirrors the canonical skills/
directory at the repo root onto the CDN URL surface in memory — no
symlinks, no committed duplicates. Three URL patterns, all derived
dynamically from skills/ contents:
/SKILL.md -> skills/SKILL.md
/skills/<...> -> skills/<...> (full tree)
/<sub-skill>/SKILL.md -> skills/<sub-skill>/SKILL.md
(compat for URLs referenced in older
CLIs' bundled root SKILL.md)
configureServer handles dev requests via middleware; generateBundle
emits every path into dist/ for the Cloudflare Pages build. Adding
skills/<new-skill>/SKILL.md starts serving both /skills/<new-skill>/
and /<new-skill>/ automatically on the next dev-server start or
build — this restores the dynamism the old pre-commit hook had,
without committing anything to git.
Verified that `pnpm run build` emits all 8 expected SKILL.md paths
(root, four under /skills/, three sub-skill siblings at root), each
with the correct per-skill content.
Skills reference explicit polygon-agent commands and flags — a CLI predating a given skill revision will fail with "Unknown argument" or "command not found" when the agent follows example invocations. Without a self-diagnostic pointer, the agent has no way to identify this as a version-drift issue. Add a compact section right after Prerequisites pointing the agent at `polygon-agent --version`, `npm view @polygonlabs/agent-cli version`, and the upgrade command. Placed in the root SKILL.md only — it is always read first, so one well-placed note covers every sub-skill that inherits its commands from the same CLI.
05997e1 to
7cde2a0
Compare
vite.config.ts had grown to ~100 lines with the inline plugin; a build config file that quietly owns a chunk of the public URL surface is harder to discover than a plugin with a descriptive filename. Move the plugin into packages/connector-ui/vite-plugins/mirror-skills.ts and import it. Behaviour-preserving move — build output is byte-identical. The following commit tightens the emit contract. Also extend tsconfig.node.json's include to cover the new plugin file so it gets typechecked alongside vite.config.ts.
…aths
The recursive walk that emitted /skills/<...> was inherited from the
old pre-commit hook's copyDir. It would blindly publish every file
under skills/ — a stray .DS_Store, a repo-local README explaining
the skill-authoring convention, lint config, any future
skills/examples/foo.md would all reach the CDN with no gatekeeping.
Drop the walk. The SKILL protocol defines exactly one file per skill
directory (SKILL.md), so the emit surface is now an explicit
enumeration of that contract:
/SKILL.md <- skills/SKILL.md
/skills/SKILL.md <- skills/SKILL.md
/skills/<sub-skill>/SKILL.md <- skills/<sub-skill>/SKILL.md
/<sub-skill>/SKILL.md <- skills/<sub-skill>/SKILL.md
(flattened mirror, compat with
URLs in older CLIs' root SKILL.md)
Anything else in skills/ — whether accidental (.DS_Store) or
intentional (examples, images) — is not served. If a future
sub-skill needs non-SKILL.md assets, extend the plugin explicitly.
Middleware's resolveRequest tightened to match: only recognises
/SKILL.md, /skills/SKILL.md, /<name>/SKILL.md, and
/skills/<name>/SKILL.md. Path traversal guarded by the regex
(single path component only) plus the existing withinSkillsDir
check for defence in depth.
Build output unchanged — same 8 SKILL.md paths in dist/ with
identical byte content to the previous commit.
| const file = resolveRequest(url); | ||
| if (file && withinSkillsDir(file) && existsSync(file) && statSync(file).isFile()) { | ||
| res.setHeader('content-type', 'text/markdown; charset=utf-8'); | ||
| res.end(readFileSync(file)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Failing run: https://github.com/0xPolygon/polygon-agent-cli/actions/runs/24717552967/job/72297775568
The problem
Release failed at `lerna-signed-release.sh` Stage 3 with `jq: Argument list too long`. Pulling the thread surfaced three issues worth fixing together:
Approach
Why not marked breaking
Pre-1.0 semver: 0.8.0 → 0.9.0 via `feat(cli):` (no `!`, no `BREAKING CHANGE:`, which would bump major). No consumer of the bundled path has been found anywhere. If a silent downstream existed, 0.9.1 with a pointer to `npx skills add` closes it.
Reviewer gotchas
Test plan