publish pi-ilo-lang from the release workflow#151
Merged
Conversation
ships two tools and the ilo skill so the pi coding agent can write and run ilo code without shelling out: - ilo_run: invoke `ilo <code|file> [func] [args...]`, return stdout, stderr, exit code as structured details - ilo_repl: hold one long-lived `ilo serv` subprocess (start/send/stop) with a 5 minute idle timeout and 30 second per-request timeout binary resolution: $ILO_BIN, then a bundled bin under the package, then `ilo` on $PATH. parameters declared with typebox, matching the pattern in pi-web-access. peerDeps target @mariozechner/* to match the installed pi-coding-agent 0.66.x.
one-line addition: if the agent is running inside pi with pi-ilo-lang installed, prefer the ilo_run and ilo_repl tools over shelling out. agents outside pi ignore the line.
new publish-pi job mirrors publish-npm: sparse-checkout pi/ plus skills/ilo/, copy SKILL.md and README into the package so the canonical skill is the only source, npm version from the tag, npm publish with the existing NPM_TOKEN. swallows "previously published" the same way the existing job does so re-runs on an existing tag are safe. uses an env var for GITHUB_REF_NAME to avoid the workflow-injection shape the security hook flagged.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
addressed findings from the PR review:
- ilo_run wraps runIlo in try/catch and surfaces ENOENT cleanly
("ilo binary not found, set ILO_BIN or install ilo") instead of
letting the rejection escape the tool boundary
- ilo_repl wires the execute() AbortSignal through to sendToRepl
so cancellation no longer waits for the 30s request timeout
- sendToRepl checks process.exitCode and stdin.writable before
pushing a pending, attaches stdin error handler at startup, and
removes the pending entry on timeout/abort so the queue does not
drift if a request never gets a response line
- proc.stdout reader logs orphan response lines to stderr instead
of silently dropping them, so a protocol drift is visible
- describeIloError centralises ENOENT messaging for both tools
- removed the committed pi/skills/ilo/SKILL.md and gitignored
skills/ inside pi/ so the canonical skills/ilo/SKILL.md is the
only source. CI continues to copy it into the package before
npm publish
no behaviour changes to ilo_run on the happy path. strict TS
check still passes against the installed pi-coding-agent types.
pi/ has its own README scoped to the extension. the previous job copied README.md from the repo root into pi/ before npm publish, which would have shipped the language-level README in the pi package. drop that cp; the sparse-checkout no longer needs the top-level README either. LICENSE is still bundled in the package from pi/LICENSE which was committed alongside pi/package.json.
second-pass review caught two real issues and one false alarm: - runIlo (I1): the stdin write/end pair could throw synchronously if the child exits before we finish writing. wrap in try/catch and attach a no-op stdin error handler so EPIPE does not become an unhandled 'error' event. the existing close handler still resolves with whatever exit code the child reported. - ilo_repl (I2): the previous stdin error handler shifted the head pending and rejected it. with pipelined sends that mis-attributes the failure. drop the shift; let the process 'close' / 'error' handlers drain every in-flight pending. stdin error handler stays but is now a no-op so EPIPE does not crash the process. I3 was a false alarm: pi/LICENSE is already committed in pi/, so the sparse-checkout pulls it. no copy step needed.
publish-pi previously had no needs: clause, which meant a failing Rust build or release step would not block the pi package from shipping. that could put pi-ilo-lang@X.Y.Z on npm pointing at a tag whose binaries never made it onto github releases. add needs: [release] to mirror publish-crates. drop the redundant LICENSE entry from the sparse-checkout list since pi/LICENSE is committed in the repo and pulled by sparse-checkout pi.
This was referenced May 11, 2026
Merged
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.
Summary
pi/package (pi-ilo-lang) with two tools -ilo_runandilo_repl- plus the canonical ilo skill, so the pi coding agent can write and run ilo without shelling outskills/ilo/SKILL.mdpointing agents at those tools when they're inside pipublish-pijob inrelease.ymlthat npm-publishespi-ilo-langon everyv*tag, mirroring howpublish-npmworks todayWhy
Pi already runs the same skill I ship to Claude Code and Codex, but it has to shell out to
ilovia the generic bash tool, which means a permission prompt per call and no structure on the output. A real pi extension fixes both. The REPL tool uses ilo's documentedservJSON loop so a session can be held open for iterative work, with a 5 minute idle timeout.Behaviour notes
ilo_runresolves the binary as$ILO_BIN-> bundlednode_modules/.bin/ilo->iloon$PATHilo_replkeeps a singleilo servchild per pi process, with one request and one response persend, matching theservprotocol inilo --helppi-web-accessuses@mariozechner/*to match the installedpi-coding-agent0.66.xTest plan
@mariozechner/pi-coding-agenttypes under strict mode)npm packfrompi/produces a tarball that containsextensions/,skills/ilo/SKILL.md,README.md,LICENSEv*tag,publish-piruns to completion andpi install npm:pi-ilo-langresolvesilo_run({ code: "+1 2" })returns stdout3ilo_repl({ command: "start" }), thensendwith a small program, thenstop, with the idle timer cleaning up ifstopis skipped