Skip to content

@relayfile/sdk: split CLI utilities (mount-launcher, cloud-login) into subpath export so they tree-shake out of Worker bundles #170

@khaliqgant

Description

@khaliqgant

Problem

@relayfile/sdk@0.7.15 (and current) bundles CLI-only utilities into its main entry point. dist/index.js does:

export { createDefaultMountLauncher, defaultMountLauncher, readMountedWorkspaceStatus } from "./mount-launcher.js";

mount-launcher.js uses node:child_process, and cloud-login.js uses node:http + node:child_process. Both are CLI/Node-only paths.

Combined with package.json: { "sideEffects": null }, this means esbuild cannot tree-shake these files out of any bundle that imports @relayfile/sdk — even bundles that never call the CLI functions. The CLI code is always pulled in.

Impact (cross-repo: AgentWorkforce/cloud)

In AgentWorkforce/cloud, the agent-gateway Cloudflare Worker pulls in @relayfile/sdk transitively via @agent-relay/events@agent-relay/sdk → @relayfile/sdk@0.7.15. The agent-gateway runtime never calls createDefaultMountLauncher or related, but esbuild bundles them anyway.

This broke the b1-worker-import-safety bundle-scan test (cloud PR #844). The workaround in that PR is to externalize node:child_process for the agent-gateway entry with a tolerated-but-unsafe-at-runtime comment — honest, but fragile: if any future code path actually calls those exports, it will crash on the Worker.

Proposed fix

Split CLI-only utilities into a dedicated subpath export:

// package.json
"exports": {
  ".": "./dist/index.js",
  "./cli": "./dist/cli/index.js",
  "./mount-launcher": "./dist/cli/mount-launcher.js",
  "./cloud-login": "./dist/cli/cloud-login.js"
}

And in dist/index.js, remove the export { ... } from "./mount-launcher.js" line. Consumers that need the CLI bits can import from @relayfile/sdk/cli or @relayfile/sdk/mount-launcher explicitly. The default @relayfile/sdk entry stays Worker-safe.

Alternative if subpaths are too disruptive: add "sideEffects": ["./dist/index.js"] (or a more conservative explicit allowlist) so esbuild's tree-shaker can drop the unused mount-launcher/cloud-login imports when the consumer doesn't reference them.

After this lands

In AgentWorkforce/cloud, the agent-gateway bundle-scan in tests/b1-worker-import-safety.test.ts can drop the node:child_process from AGENT_GATEWAY_ADDITIONAL_EXTERNALS and tighten the scan back to "any Worker-incompatible import = fail" (the proper bar).

Related

  • AgentWorkforce/cloud#844 (workaround in agent-gateway bundle-scan)
  • AgentWorkforce/cloud#827 (agent-gateway SST infra)
  • Discovered during WS-OPTION-B autonomous run (cloud #842/#840/#841 saga)

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions