Files
composiohq__composio/mise.toml
T
Alberto Schiabel 64406ff359 chore(cli): bump Bun to 1.4.0 and replace tar with Bun.Archive (#4183)
Bumps the mise-pinned Bun toolchain from 1.3.10 to 1.4.0 and replaces
the one CLI dependency that a Bun 1.4 built-in can verifiably take over.

## Binary size: Linux shrinks a lot, macOS grows a little

Measured per target, byte counts from `build:binary:all` on a
darwin-arm64 host.

| Target | Before (1.3.10) | After runtime (1.4.0) | After full | Δ
total | Δ % |
|---|---:|---:|---:|---:|---:|
| `composio-darwin-aarch64` | 80,850,704 (77.1 MiB) | 83,790,962 (79.9
MiB) | 83,790,962 (79.9 MiB) | +2,940,258 (+2.8 MiB) | +3.6% |
| `composio-darwin-x64` | 85,710,240 (81.7 MiB) | 90,430,880 (86.2 MiB)
| 90,430,880 (86.2 MiB) | +4,720,640 (+4.5 MiB) | +5.5% |
| `composio-linux-x64` | 123,666,298 (117.9 MiB) | 102,270,152 (97.5
MiB) | 102,270,152 (97.5 MiB) | -21,396,146 (-20.4 MiB) | -17.3% |
| `composio-linux-aarch64` | 121,153,270 (115.5 MiB) | 102,221,816 (97.5
MiB) | 102,221,816 (97.5 MiB) | -18,931,454 (-18.1 MiB) | -15.6% |

**Attribution — read this before quoting the numbers.** Every byte of
movement above comes from the **Bun runtime bump**, not from dependency
removal. The "after runtime" and "after full" columns are
byte-identical: the only dependency dropped here is `tar`, a
devDependency used by one build script that never reaches the binary.
Its size contribution is exactly **0 bytes**. (The identical columns
also confirm the compiled build is reproducible across runs.)

Linux users — the large majority of installs — get a ~18-20 MiB smaller
binary. macOS grows 2.8-4.5 MiB. This matches the direction upstream
reports for the standalone Bun binary.

## What changed

- `mise.toml` pins `bun = "1.4.0"`; `mise.lock` regenerated with the
exact platform list `ts.audit` uses.
- `scripts/_acp-adapters.ts` extracts npm tarballs with `Bun.Archive`
instead of the `tar` package.
- `tar` dropped from `@composio/cli` devDependencies (plus
`@isaacs/fs-minipass`, `chownr`, `minizlib`, `yallist` from the
lockfile).

## Verified negative results

These are the two adjacent candidates a reviewer would expect to see
replaced. Both were probed against a real Bun 1.4.0 binary and both fail
— recorded here so nobody re-derives the dead ends:

- **`extract-zip` stays.** `Bun.Archive` cannot read zip: `new
Bun.Archive(zipBytes)` throws `Unrecognized archive format`, and
`ArchiveOptions.compress` accepts only `"gzip"`. Still used at three
call sites.
- **`semver` stays.** `Object.keys(Bun.semver)` returns exactly
`["satisfies", "order"]`. The CLI also needs `valid`, `prerelease`,
`compare`, `gt`, and `lt`. `valid` and `prerelease` have no equivalent,
so a partial migration would only add a second semver dialect.

## `json5` → `Bun.JSON5` was attempted and backed out

`parse-json.ts` is covered by the CLI's Vitest suite, which runs on
**Node**, where the `Bun` global does not exist — `Bun.JSON5.parse`
throws `ReferenceError` under test. The suite cannot move to the Bun
runtime (88 of 122 files fail there on unrelated zod resolution errors),
and `bun test` for a single file would conflict with the repo's
`@effect/vitest` lint rule.

The swap itself is sound — `Bun.JSON5.parse` matched the `json5` package
on all nine contract cases against a real 1.4.0 binary, including
`SyntaxError` on malformed input. It is the test harness, not the
parser, that blocks it. Deferred rather than shipped with weakened
coverage.

For sizing the follow-up: `--metafile-md` puts `json5` at **28,045 bytes
(0.1%)** of the JS bundle, imported only by `src/utils/parse-json.ts` —
roughly 0.03% of a compiled binary. Worth doing for dependency-surface
reasons, not for size.

## Verification

- All four release targets cross-compile on Bun 1.4.0.
- `mise lock --platform linux-x64,linux-arm64,macos-arm64,macos-x64`
then `git diff --exit-code mise.lock` is clean, replayed in a CI-like
environment.
- `pnpm typecheck` clean; CLI suite green (122 files, 1248 passed, 1
skipped).
- `Bun.Archive` adapter build against the live npm registry produces
codex-acp binaries **byte-identical** (SHA-256) to the `tar`-produced
ones, at the same `package/bin/<name>` paths, executable after `chmod`,
extracted concurrently. A truncated tarball throws `ReadError` rather
than silently yielding an empty directory.
- Runtime smoke on the 1.4.0 binary: `composio version`, `composio
--help`, and the `composio run` companion-module spawn path (reports
`process.version` v26.3.0 — no Node 26 stream regression). `extract-zip`
verified working under the new runtime.

### Not run locally

`pnpm test:e2e:cli` needs Docker, which was unavailable on this machine.
CI covers it. Worth a look at that job: the e2e image is version-keyed
and has served a stale Bun binary from a cached layer before, so confirm
the container reports 1.4.0.

## Notes

- `@types/bun` is deliberately not bumped: `Bun.JSON5` and `Bun.Archive`
are already declared in the installed `bun-types@1.3.14`, no
`@types/bun` 1.4.x exists yet, and `minimumReleaseAge` would block a
fresh pin anyway.
- No changeset: `@composio/cli` is in `.changeset/config.json`'s
`ignore` list and no published package is touched.
- `mise lock` locally adds a stray `[[tools.node]] 24.19.0` block
sourced from the developer's global mise config. It was stripped; the
committed lock is stable under the audit gate's exact command.
2026-08-20 20:02:44 +02:00

27 lines
771 B
TOML

# Single source of truth for Node, Bun, Deno, Python, uv, and pnpm versions.
#
# Local dev: `mise install` (after `brew install mise` / `winget install jdx.mise` / `curl https://mise.run | sh`)
# CI: exact versions are read from `mise.lock` by the composite actions
# under `.github/actions/` and installed with allowlisted setup actions
#
# pnpm is pinned through mise's npm backend so mise owns the full local and CI
# toolchain. We do not rely on Corepack because Node.js no longer distributes it
# starting with v25.
min_version = "2026.1.0"
[tools]
"npm:pnpm" = "11.8.0"
node = "24.17.0"
bun = "1.4.0"
deno = "2.6.7"
python = "3.12"
uv = "0.8.19"
[env]
_.path = ["{{config_root}}/node_modules/.bin"]
[settings]
lockfile = true
locked = true