mirror of
https://github.com/qwibitai/nanoclaw.git
synced 2026-06-18 18:29:35 +08:00
adfae67611
The agent's global Node CLIs (claude-code, agent-browser, vercel) were each
a hardcoded ARG + RUN layer in the Dockerfile, so adding or bumping one meant
editing the Dockerfile — a code reach-in every tool-installing skill had to make.
Move the tool list into container/cli-tools.json. A skill now adds a CLI by
appending a {name, version} entry (a json-merge) — the safest change shape:
deterministic, idempotent, removable. install-cli-tools.sh parses the manifest
with node (no new jq dep), writes the per-tool only-built-dependencies opt-ins,
and runs one pinned `pnpm install -g`, so the pnpm supply-chain path is unchanged.
Behavior is byte-for-byte: same opt-ins, same pinned installs. agent-browser is
now pinned (0.27.1, what `latest` last resolved to) instead of floating.
container/cli-tools.test.ts guards the seam: red if a baseline tool is dropped,
a version unpins, or the Dockerfile wiring / pnpm path is removed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
30 lines
1.3 KiB
Bash
30 lines
1.3 KiB
Bash
#!/bin/sh
|
|
# Install the global Node CLIs the agent invokes at runtime, from cli-tools.json.
|
|
#
|
|
# A skill adds a tool by appending a { "name", "version" } entry to that
|
|
# manifest (a json-merge) instead of editing the Dockerfile — the reach-in
|
|
# becomes the safest change shape, deterministic and removable.
|
|
#
|
|
# Every tool is installed via `pnpm install -g`, pinned to an exact version, so
|
|
# the pnpm supply-chain policy still applies. Tools with a native postinstall
|
|
# set "onlyBuilt": true to opt in to running build scripts (pnpm skips them by
|
|
# default). Run as root before `USER node`, so /root/.npmrc is the right home.
|
|
set -eu
|
|
|
|
MANIFEST="${1:-/tmp/cli-tools.json}"
|
|
|
|
# Write the per-tool only-built-dependencies opt-ins pnpm reads at install time.
|
|
node -e '
|
|
const tools = require(process.argv[1]);
|
|
const optIns = tools.filter((t) => t.onlyBuilt).map((t) => "only-built-dependencies[]=" + t.name);
|
|
require("fs").writeFileSync("/root/.npmrc", optIns.join("\n") + (optIns.length ? "\n" : ""));
|
|
' "$MANIFEST"
|
|
|
|
# Install every tool, pinned. name@version specs never contain spaces, so the
|
|
# unquoted expansion word-splits cleanly into positional args.
|
|
# shellcheck disable=SC2046
|
|
set -- $(node -e 'require(process.argv[1]).forEach((t) => console.log(t.name + "@" + t.version))' "$MANIFEST")
|
|
if [ "$#" -gt 0 ]; then
|
|
pnpm install -g "$@"
|
|
fi
|