Skip to content

Reactor.Cli can't build offline: one command forces a build-time npm download #1133

Description

Summary

src/Reactor.Cli cannot be built without network access, because GitHub.Copilot.SDK downloads a platform-specific Copilot CLI npm tarball during BeforeBuild. The dependency exists to serve exactly one command — mur loc translate — but the cost is paid by every build of every other command.

Repro

dotnet build src\Reactor.Cli -c Debug -p:Platform=x64
GitHub.Copilot.SDK.targets(108,5): error MSB3923: Failed to download file
"https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79.tgz".
The SSL connection could not be established ... TLS alert: 'HandshakeFailure'.

Workaround:

dotnet build src\Reactor.Cli -c Debug -p:Platform=x64 -p:CopilotSkipCliDownload=true

The coupling

GitHub.Copilot.SDK has exactly one consumer in the CLI:

src/Reactor.Cli/Loc/AzureOpenAiProvider.cs:2    using GitHub.Copilot;
src/Reactor.Cli/Loc/AzureOpenAiProvider.cs:33   await using var client = new CopilotClient();

(The other files matching "Copilot" reference it only in comments or env-var names. The file is renamed to CopilotTranslationProvider.cs in #1129.)

So building mur check, mur doctor, mur docs, or mur --create from source requires fetching an npm package that only mur loc translate will ever use.

Why it's worth addressing

  • Offline and restricted-network builds fail with an error that doesn't point at the fix. MSB3923 naming an npm registry gives no hint that -p:CopilotSkipCliDownload=true exists.
  • The opt-out is silently lossy. Building with the skip flag produces a mur whose loc translate will fail at runtime, with nothing recording that the binary is degraded.
  • The blast radius is disproportionate. One command's optional AI backend gates the whole CLI's buildability.

Options

  1. Move the translation backend into its own assembly loaded on demand, so GitHub.Copilot.SDK isn't in the CLI's build graph. Cleanest, most work.
  2. Make the download lazy/tolerant — set CopilotSkipCliDownload=true by default and have loc translate fetch or diagnose at first use, with a clear "run X to enable translation" message.
  3. Minimum, cheap: keep current behaviour but catch the failure and emit an actionable message naming the opt-out property, and have loc translate fail at startup with a clear diagnostic when the binary was built without the asset.

Even option 3 removes most of the pain, since the current failure is a raw MSB3923 with no breadcrumb.

Context

Relevant to the broader question of whether mur loc is earning its keep: loc translate is the least-evidenced command in the CLI (there are zero .resw files anywhere in the repo), yet it is the one imposing a build-time network dependency on everything else.

Discovered while building mur from source at 88ef6db4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions