Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@
"dependencies": {
"@agentclientprotocol/sdk": "^1.2.1",
"@anthropic-ai/claude-agent-sdk": "^0.2.123",
"@fastify/swagger": "9.7.0",
"@happier-dev/agents": "0.0.0",
"@happier-dev/cli-common": "0.0.0",
"@happier-dev/connection-supervisor": "0.0.0",
Expand All @@ -147,15 +146,13 @@
"@happier-dev/release-runtime": "0.0.0",
"@huggingface/transformers": "^3.8.1",
"@modelcontextprotocol/sdk": "^1.26.0",
"@stablelib/base64": "^2.0.1",
"@stablelib/hex": "^2.0.1",
"@types/cross-spawn": "^6.0.6",
"@types/http-proxy": "^1.17.17",
"@types/ps-list": "^6.2.1",
"@types/qrcode-terminal": "^0.12.2",
"@types/react": "^19.2.7",
"@types/tmp": "^0.2.6",
"ai": "^5.0.107",
"archiver": "^7.0.1",
"axios": "^1.13.2",
"chalk": "^5.6.2",
Expand All @@ -165,7 +162,6 @@
"fastify": "^5.7.3",
"fastify-type-provider-zod": "6.1.0",
"http-proxy": "^1.18.1",
"http-proxy-middleware": "^3.0.5",
"https-proxy-agent": "^7.0.6",
"ink": "^6.5.1",
"@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
Expand All @@ -179,7 +175,6 @@
"sharp": "^0.34.3",
"socket.io-client": "^4.8.1",
"tar": "^7.5.8",
"tmp": "^0.2.5",
"tweetnacl": "^1.0.3",
"zod": "4.3.6"
},
Expand All @@ -194,6 +189,7 @@
"pkgroll": "^2.27.0",
"release-it": "^19.0.6",
"shx": "^0.3.3",
"tmp": "^0.2.5",
"ts-node": "^10",
"tsx": "^4.20.6",
"@typescript/native": "npm:typescript@7.0.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,68 @@ const CLI_RUNTIME_EXTERNAL_PACKAGES = [
'@homebridge/node-pty-prebuilt-multiarch',
] as const;

// Bun's `--compile` tree-shakes apps/cli's own source into the compiled binary (confirmed via
// `strings` on the real shipped binary: reachable files carry provenance comments, unreachable
// ones don't), so any statically-imported, non-external dependency reachable from that source is
// already embedded in the executable. These declared apps/cli dependencies were audited (see
// investigate/compiled-in-vs-vendored-audit) and confirmed to have no runtime code path --
// bin/*.mjs entrypoint, scripts/*.cjs sidecar, or dynamic require()/import() with a non-static
// path -- that reads them from an on-disk node_modules copy. Vendoring a duplicate loose copy of
// these onto disk alongside the compiled binary is therefore pure waste.
//
// This exclusion is scoped to the compiled CLI binary payload only (copyCliNodeRuntimePayload,
// below). Other vendorBundledPackageRuntimeDependencies call sites (npm-published tarball builds,
// apps/stack, packages/relay-server) do not compile their source into a binary and must keep
// vendoring these packages in full.
//
// Keep this list scoped to packages with concrete, checked evidence; when in doubt, leave a
// package vendored. Notably `sharp` is NOT included here: it does a runtime-constructed
// `require()` of a platform-specific native `.node` binding, the same reason node-pty is external
// above, so it must stay vendored on disk.
// Same rationale and audit trail as CLI_BINARY_PAYLOAD_VENDORING_EXCLUDED_PACKAGES above, but for
// the runtime dependencies declared by apps/cli's own bundled @happier-dev/* workspace packages
// (see bundleWorkspacePackageWithRuntimeDependencies below), rather than apps/cli's own
// dependencies. Confirmed via `strings` on a real compiled binary that these packages' distinctive
// exports (not just an inert package-name string) are compiled in -- e.g. @happier-dev/protocol's
// own nested tweetnacl/@noble/hashes/base64-js/zod-to-json-schema copies -- and that no sidecar or
// dynamic require() reads any of them from disk. See investigate/workspace-bundle-vendoring-audit.
//
// Scoped to the compiled CLI binary payload only, same as CLI_BINARY_PAYLOAD_VENDORING_EXCLUDED_PACKAGES.
const CLI_BINARY_PAYLOAD_WORKSPACE_BUNDLE_VENDORING_EXCLUDED_PACKAGES = new Set<string>([
'@noble/hashes',
'base64-js',
'tweetnacl',
'zod-to-json-schema',
]);

const CLI_BINARY_PAYLOAD_VENDORING_EXCLUDED_PACKAGES = new Set<string>([
'@agentclientprotocol/sdk',
'@anthropic-ai/claude-agent-sdk',
'@modelcontextprotocol/sdk',
'@stablelib/hex',
'archiver',
'axios',
'chalk',
'cross-spawn',
'diff',
'expo-server-sdk',
'fastify',
'fastify-type-provider-zod',
'http-proxy',
'https-proxy-agent',
'ink',
'open',
'openapi-types',
'ps-list',
'qrcode-terminal',
'react',
'react-devtools-core',
'socket.io-client',
'tar',
'tmp',
'zod',
]);

type CliToolUnpackModule = {
unpackTools?: (options: Readonly<{ platformDir: string; toolsDir: string }>) => Promise<unknown> | unknown;
};
Expand Down Expand Up @@ -116,12 +178,14 @@ async function copyCliNodeRuntimePayload(
vendorBundledPackageRuntimeDependencies({
srcPackageJsonPath: join(cliDir, 'package.json'),
destPackageDir: payloadDir,
excludePackageNames: CLI_BINARY_PAYLOAD_VENDORING_EXCLUDED_PACKAGES,
});
for (const { packageName, srcDir } of workspaceBundles) {
bundleWorkspacePackageWithRuntimeDependencies({
packageName,
srcDir,
destDir: join(payloadDir, 'node_modules', ...packageName.split('/')),
excludePackageNames: CLI_BINARY_PAYLOAD_WORKSPACE_BUNDLE_VENDORING_EXCLUDED_PACKAGES,
});
}
}
Expand Down
Loading
Loading