Files
deepseek-harness/.agents/notes/implemented/process/2026-08-19-offline-pnpm-prefetch-scripts.md
Coder ed152416d5
Some checks failed
CI / node 22.19 (push) Has been skipped
CI / node 26 (push) Has been skipped
CI / python 3.10 / keyless SDK (push) Has been skipped
CI / python runtime / release-shaped Linux x64 (push) Has been skipped
CI / windows node 24 / wine blocking (push) Has been skipped
CI / wine apt cache (push) Successful in 58s
CI / serial / linux (push) Has been skipped
Deploy documentation / build (push) Failing after 2m46s
Deploy documentation / deploy (push) Has been skipped
E2E (real DeepSeek API) / e2e (push) Failing after 1m18s
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Failing after 1m18s
Landlock Run / Matrix (push) Successful in 13s
Release (vendor) / Pack npm tarballs (push) Failing after 3m43s
Release (dsh) / Pack npm tarballs (push) Failing after 1m53s
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Failing after 1m51s
Release (vendor) / Publish to npm (push) Has been skipped
Release (dsh) / Publish to npm (push) Has been skipped
CI / node 24 / static (push) Has been cancelled
CI / node 24 / coverage (push) Has been cancelled
CI / node 24 / snapshots and artifacts (push) Has been cancelled
CI / windows node 24 / native complete (push) Has been cancelled
CI / serial / linux (self-hosted standby) (push) Has been cancelled
CI / serial / macos (push) Has been cancelled
CI / serial / windows (self-hosted standby) (push) Has been cancelled
CI / larger-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
CI / all checks passed (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
Landlock Run / ${{ matrix.platform }} (push) Has been cancelled
Landlock Run / darwin (no platform package — degradation proof) (push) Has been cancelled
feat: add searxng web-search provider, openrouter cost balance UI, offline scripts; update source-launch and docs
2026-08-20 13:01:40 +07:00

5.3 KiB

Agent Note: Offline pnpm prefetch scripts

Status: implemented

English | 中文

Problem

A source checkout cannot boot dsh web until a supported Node runtime, pnpm install, and pnpm run build have materialized node_modules, package lib/ output, and apps/web/dist. Install reaches the npm registry (and Corepack reaches it for pnpm@11.7.0); the Node distro comes from nodejs.org/dist. Node's fetch client cannot use socks5h:// proxies, so a machine whose only ambient proxy is SOCKS fails pnpm install even while curl through the same proxy succeeds. An air-gapped follow-up install therefore needs a same-OS prefetch of the official Node archive, the lockfile store, and a Corepack home that does not call the registry.

Decision

scripts/offline/download-deps (POSIX twin .sh) runs while nodejs.org and the registry are reachable. It downloads the official Node zip/tar for the current OS and CPU from DSH_NODE_DIST_BASE (default https://nodejs.org/dist), verifies SHASUMS256.txt, unpacks into ignored .offline-cache/node/runtime, and writes .offline-cache/node/runtime.json. The Node version is DSH_NODE_VERSION when set, otherwise the running Node when it satisfies engines.node (^22.19.0 || >=24.0.0), otherwise the newest v24.x from index.json that publishes this platform's archive. It then sets COREPACK_HOME to .offline-cache/corepack, corepack prepares the root package.json packageManager pin using that Node, and pnpm fetch --frozen-lockfile --store-dir .offline-store. scripts/offline/install-deps (POSIX twin .sh) unpacks the cached Node if needed, prepends it to PATH, sets COREPACK_ENABLE_NETWORK=0, and runs pnpm install --offline --frozen-lockfile against that store. Optional -Build / --build runs npm run build:lib then pnpm --dir apps/web run build, avoiding the nested pnpm --filter invocation inside npm run build:web that can pick a different Corepack pnpm than packageManager.

DSH_NPM_HTTP_PROXY, when set, is an HTTP overlay applied only around corepack prepare and pnpm fetch, then the process proxy variables are restored so a caller SOCKS session is unchanged. curl uses the inherited HTTP_PROXY / HTTPS_PROXY / ALL_PROXY (SOCKS included) and falls back to DSH_NPM_HTTP_PROXY only when none of those are set. A socks5 or socks5h value for Node/pnpm (from DSH_NPM_HTTP_PROXY, or from the inherited proxies when no HTTP overlay is set) fails before Corepack runs, because that scheme is not a supported pnpm transport.

The scripts prefetch Node and the lockfile for the host OS and CPU they run on. They do not download LLM weights, Playwright browsers, or a local inference server. Copy the checkout including .offline-store and .offline-cache to the offline machine.

Alternatives considered

Tell contributors to copy a finished node_modules tree and skip a second install. A copied isolated pnpm layout is host-specific and breaks when the store path or package content-address links do not match; pnpm install --offline against a fetched store is the documented pnpm air-gap path.

Check supportedArchitectures into the download script so one store serves win32 and linux. Rejected for the default: optional native packages (esbuild, koffi, node-pty) must match the install host, and a mixed store still needs a same-OS install to unpack the right binaries. Cross-OS prefetch remains an explicit local pnpm fetch config, not the script default.

Add root package.json scripts that call these files. Nested pnpm under npm run is what already mismatches Corepack versions on build:web; the wrappers stay invoked as files so they control COREPACK_HOME and --store-dir.

Overwrite the caller's HTTP_PROXY for the whole download script. Rejected: .\download-deps.ps1 runs in the current PowerShell session, so a session-wide overwrite would replace a working SOCKS proxy for later commands. curl can use SOCKS; only Node/pnpm need the HTTP overlay, and only for those child processes.

Ship the Node MSI or pkg installer. Rejected: those installers need administrator rights and a global install; the official zip/tar is relocatable, and install only unpacks it and prepends PATH.

Hardcode one Node version in the script. Rejected: a pinned patch goes stale against engines.node and CI (22.19, 24, 26). Matching the running Node keeps optional native packages aligned with the prefetch host; index.json is the fallback when Node is not on PATH.

Vendor the pnpm store in git. The store is hundreds of megabytes of registry tarballs; .gitignore keeps .offline-store/ and .offline-cache/ untracked.

Consequences

Air-gap preparation is a two-command, same-OS pair and does not change the online pnpm install path. The offline machine does not need a preinstalled Node: install unpacks the cached official distro. dsh plugin … add of a registry or git spec still needs a network on the machine that runs it. Local chat still needs a separately installed OpenAI-compatible server; these scripts do not substitute for that.